Imported Upstream version 2.6.0
This commit is contained in:
parent
26fb71b504
commit
459aaf9392
510 changed files with 40508 additions and 18859 deletions
551
drivers/belkin.c
551
drivers/belkin.c
|
|
@ -28,7 +28,10 @@
|
|||
#include "belkin.h"
|
||||
|
||||
#define DRIVER_NAME "Belkin Smart protocol driver"
|
||||
#define DRIVER_VERSION "0.22"
|
||||
#define DRIVER_VERSION "0.24"
|
||||
|
||||
static int init_communication(void);
|
||||
static int get_belkin_reply(char *buf);
|
||||
|
||||
/* driver description structure */
|
||||
upsdrv_info_t upsdrv_info = {
|
||||
|
|
@ -41,29 +44,33 @@ upsdrv_info_t upsdrv_info = {
|
|||
|
||||
static void send_belkin_command(char cmd, const char *subcmd, const char *data)
|
||||
{
|
||||
ser_flush_io(upsfd);
|
||||
|
||||
ser_send(upsfd, "~00%c%03d%s%s", cmd, (int)strlen(data) + 3, subcmd, data);
|
||||
|
||||
upsdebugx(3, "Send Command: %s, %s", subcmd, data);
|
||||
}
|
||||
|
||||
static int init_communication(void)
|
||||
{
|
||||
int i;
|
||||
int res;
|
||||
int i, res;
|
||||
char temp[SMALLBUF];
|
||||
|
||||
res = -1;
|
||||
for (i = 1; i <= 10 && res == -1; i++) {
|
||||
send_belkin_command(STATUS,MANUFACTURER,"");
|
||||
for (i = 0; i < 10; i++) {
|
||||
send_belkin_command(STATUS, MANUFACTURER, "");
|
||||
res = get_belkin_reply(temp);
|
||||
|
||||
if (res > 0) {
|
||||
/* return the number of retries needed before a valid reply is read (discard contents) */
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (res == -1 || strcmp(temp,"BELKIN"))
|
||||
return res;
|
||||
|
||||
return 0;
|
||||
/* no valid reply read */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *get_belkin_field(const char *in, char *out, size_t outlen,
|
||||
size_t num)
|
||||
static char *get_belkin_field(const char *in, char *out, size_t outlen, size_t num)
|
||||
{
|
||||
size_t i, c = 1;
|
||||
char *ptr;
|
||||
|
|
@ -73,22 +80,26 @@ static char *get_belkin_field(const char *in, char *out, size_t outlen,
|
|||
snprintf(out, outlen, "%s", in);
|
||||
ptr = strchr(out, ';');
|
||||
|
||||
if (ptr)
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < strlen(in); i++) {
|
||||
if (in[i] == ';')
|
||||
if (in[i] == ';') {
|
||||
c++;
|
||||
}
|
||||
|
||||
if (c == num) {
|
||||
snprintf(out, outlen, "%s", &in[i + 1]);
|
||||
ptr = strchr(out, ';');
|
||||
|
||||
if (ptr)
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
|
@ -96,204 +107,16 @@ static char *get_belkin_field(const char *in, char *out, size_t outlen,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static int do_status(void)
|
||||
{
|
||||
char temp[SMALLBUF], st[SMALLBUF];
|
||||
int res;
|
||||
|
||||
send_belkin_command(STATUS,STAT_STATUS,"");
|
||||
res = get_belkin_reply(temp);
|
||||
if (res == -1) {
|
||||
dstate_datastale();
|
||||
return 0;
|
||||
}
|
||||
|
||||
status_init();
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 6);
|
||||
if (*st == '1') {
|
||||
status_set("OFF");
|
||||
|
||||
} else { /* (OFF) and (OB | OL) are mutually exclusive */
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 2);
|
||||
if (*st == '1') {
|
||||
status_set("OB");
|
||||
|
||||
send_belkin_command(STATUS,STAT_BATTERY,"");
|
||||
res = get_belkin_reply(temp);
|
||||
|
||||
if (res == -1) {
|
||||
dstate_datastale();
|
||||
return 0;
|
||||
}
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 10);
|
||||
res = atoi(st);
|
||||
get_belkin_field(temp, st, sizeof(st), 2);
|
||||
|
||||
if (*st == '1' || res < LOW_BAT)
|
||||
status_set("LB"); /* low battery */
|
||||
}
|
||||
else
|
||||
status_set("OL"); /* on line */
|
||||
}
|
||||
|
||||
status_commit();
|
||||
dstate_dataok();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int do_broken_rat(char *buf)
|
||||
{
|
||||
int ret, cnt;
|
||||
char tmp[8];
|
||||
|
||||
usleep(25000);
|
||||
|
||||
ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 3, 0);
|
||||
|
||||
if (ret != 7)
|
||||
return -1;
|
||||
|
||||
tmp[7] = '\0';
|
||||
cnt = atoi(tmp + 4);
|
||||
|
||||
if ((cnt < 1) || (cnt > 255))
|
||||
return -1;
|
||||
|
||||
usleep(5000 * cnt);
|
||||
|
||||
/* firmware 001 only sends 50 bytes instead of the proper 53 */
|
||||
if (cnt == 53)
|
||||
cnt = 50;
|
||||
|
||||
ret = ser_get_buf_len(upsfd, (unsigned char *)buf, 50, cnt, 0);
|
||||
buf[cnt] = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int init_ups_data(void)
|
||||
{
|
||||
int res;
|
||||
double low, high;
|
||||
char temp[SMALLBUF], st[SMALLBUF];
|
||||
|
||||
send_belkin_command(STATUS, MODEL, "");
|
||||
res = get_belkin_reply(temp);
|
||||
if (res == -1)
|
||||
return res;
|
||||
|
||||
dstate_setinfo("ups.model", "%s", temp);
|
||||
|
||||
send_belkin_command(STATUS, VERSION_CMD, "");
|
||||
res = get_belkin_reply(temp);
|
||||
if (res == -1)
|
||||
return res;
|
||||
|
||||
dstate_setinfo("ups.firmware", "%s", temp);
|
||||
|
||||
/* deal with stupid firmware that breaks RAT */
|
||||
|
||||
send_belkin_command(STATUS, RATING, "");
|
||||
|
||||
if (!strcmp(temp, "001"))
|
||||
res = do_broken_rat(temp);
|
||||
else
|
||||
res = get_belkin_reply(temp);
|
||||
|
||||
if (res > 0) {
|
||||
get_belkin_field(temp, st, sizeof(st), 8);
|
||||
low = atof(st) / 0.88;
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 9);
|
||||
high = atof(st) * 0.88;
|
||||
|
||||
dstate_setinfo("input.transfer.low", "%03.1f", low);
|
||||
dstate_setinfo("input.transfer.high", "%03.1f", high);
|
||||
}
|
||||
|
||||
ser_flush_io(upsfd);
|
||||
|
||||
dstate_addcmd("load.off");
|
||||
dstate_addcmd("load.on");
|
||||
upsdrv_updateinfo();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* normal idle loop - keep up with the current state of the UPS */
|
||||
void upsdrv_updateinfo(void)
|
||||
{
|
||||
int res;
|
||||
double val;
|
||||
char temp[SMALLBUF], st[SMALLBUF];
|
||||
|
||||
if (!do_status())
|
||||
return;
|
||||
|
||||
send_belkin_command(STATUS, STAT_INPUT, "");
|
||||
res = get_belkin_reply(temp);
|
||||
if (res == -1)
|
||||
return;
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 3);
|
||||
val = atof(st) / 10;
|
||||
dstate_setinfo("input.voltage", "%05.1f", val);
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 2);
|
||||
val = atof(st) / 10;
|
||||
dstate_setinfo("input.frequency", "%.1f", val);
|
||||
|
||||
send_belkin_command(STATUS,STAT_BATTERY, "");
|
||||
res = get_belkin_reply(temp);
|
||||
if (res == -1)
|
||||
return;
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 10);
|
||||
val = atof(st);
|
||||
dstate_setinfo("battery.charge", "%03.0f", val);
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 9);
|
||||
val = atof(st);
|
||||
dstate_setinfo("battery.temperature", "%03.0f", val);
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 7);
|
||||
val = atof(st) / 10;
|
||||
dstate_setinfo("battery.voltage", "%4.1f", val);
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 9);
|
||||
val = atof(st);
|
||||
dstate_setinfo("ups.temperature", "%03.0f", val);
|
||||
|
||||
send_belkin_command(STATUS, STAT_OUTPUT, "");
|
||||
res = get_belkin_reply(temp);
|
||||
if (res == -1)
|
||||
return;
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 2);
|
||||
val = atof(st) / 10;
|
||||
dstate_setinfo("output.frequency", "%.1f", val);
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 4);
|
||||
val = atof(st) / 10;
|
||||
dstate_setinfo("output.voltage", "%05.1f", val);
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 7);
|
||||
val = atof(st);
|
||||
dstate_setinfo("ups.load", "%03.0f", val);
|
||||
}
|
||||
|
||||
static int get_belkin_reply(char *buf)
|
||||
{
|
||||
int ret, cnt;
|
||||
int ret;
|
||||
long cnt;
|
||||
char tmp[8];
|
||||
|
||||
usleep(25000);
|
||||
|
||||
/* pull first 7 bytes to get data length - like ~00S004 */
|
||||
ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 3, 0);
|
||||
/* pull first 7 bytes to get data length - like ~00D004 */
|
||||
ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 2, 0);
|
||||
|
||||
if (ret != 7) {
|
||||
ser_comm_fail("Initial read returned %d bytes", ret);
|
||||
|
|
@ -301,21 +124,28 @@ static int get_belkin_reply(char *buf)
|
|||
}
|
||||
|
||||
tmp[7] = 0;
|
||||
cnt = atoi(tmp + 4);
|
||||
cnt = strtol(tmp + 4, NULL, 10);
|
||||
upsdebugx(3, "Received: %s", tmp);
|
||||
|
||||
if ((cnt < 1) || (cnt > 255))
|
||||
if (cnt == 0) { /* possible to have ~00R000, return empty response */
|
||||
buf[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((cnt < 0) || (cnt > 255)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* give it time to respond to us */
|
||||
usleep(5000 * cnt);
|
||||
|
||||
ret = ser_get_buf_len(upsfd, (unsigned char *)buf, cnt, 3, 0);
|
||||
ret = ser_get_buf_len(upsfd, (unsigned char *)buf, cnt, 2, 0);
|
||||
|
||||
buf[cnt] = 0;
|
||||
upsdebugx(3, "Received: %s", buf);
|
||||
|
||||
if (ret != cnt) {
|
||||
ser_comm_fail("Second read returned %d bytes, expected %d",
|
||||
ret, cnt);
|
||||
ser_comm_fail("Second read returned %d bytes, expected %ld", ret, cnt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -324,14 +154,206 @@ static int get_belkin_reply(char *buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int do_broken_rat(char *buf)
|
||||
{
|
||||
int ret;
|
||||
long cnt;
|
||||
char tmp[8];
|
||||
|
||||
usleep(25000);
|
||||
|
||||
/* pull first 7 bytes to get data length - like ~00D004 */
|
||||
ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 2, 0);
|
||||
|
||||
if (ret != 7) {
|
||||
ser_comm_fail("Initial read returned %d bytes", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp[7] = 0;
|
||||
cnt = strtol(tmp + 4, NULL, 10);
|
||||
upsdebugx(3, "Received: %s", tmp);
|
||||
|
||||
if (cnt == 0) { /* possible to have ~00R000, return empty response */
|
||||
buf[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((cnt < 0) || (cnt > 255)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* give it time to respond to us */
|
||||
usleep(5000 * cnt);
|
||||
|
||||
/* firmware 001 only sends 50 bytes instead of the proper 53 */
|
||||
if (cnt == 53) {
|
||||
cnt = 50;
|
||||
}
|
||||
|
||||
ret = ser_get_buf_len(upsfd, (unsigned char *)buf, cnt, 2, 0);
|
||||
|
||||
buf[cnt] = 0;
|
||||
upsdebugx(3, "Received: %s", buf);
|
||||
|
||||
if (ret != cnt) {
|
||||
ser_comm_fail("Second read returned %d bytes, expected %ld", ret, cnt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ser_comm_good();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* normal idle loop - keep up with the current state of the UPS */
|
||||
void upsdrv_updateinfo(void)
|
||||
{
|
||||
static int retry = 0;
|
||||
int res;
|
||||
char temp[SMALLBUF], st[SMALLBUF];
|
||||
|
||||
send_belkin_command(STATUS, STAT_STATUS, "");
|
||||
res = get_belkin_reply(temp);
|
||||
if (res < 0) {
|
||||
if (retry < MAXTRIES) {
|
||||
upsdebugx(1, "Communications with UPS lost: status read failed!");
|
||||
retry++;
|
||||
} else { /* too many retries */
|
||||
upslogx(LOG_WARNING, "Communications with UPS lost: status read failed!");
|
||||
dstate_datastale();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (retry) { /* previous attempt had failed */
|
||||
upslogx(LOG_WARNING, "Communications with UPS re-established");
|
||||
retry = 0;
|
||||
}
|
||||
|
||||
if (res == 0) {
|
||||
upsdebugx(1, "Ignoring empty return value after status query");
|
||||
return;
|
||||
}
|
||||
|
||||
status_init();
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 6);
|
||||
if (*st == '1') {
|
||||
status_set("OFF");
|
||||
}
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 2);
|
||||
if (*st == '1') {
|
||||
status_set("OB"); /* on battery */
|
||||
} else {
|
||||
status_set("OL"); /* on line */
|
||||
}
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 16);
|
||||
dstate_setinfo("ups.beeper.status", "%s", (*st == '0' ? "disabled" : "enabled"));
|
||||
|
||||
send_belkin_command(STATUS, STAT_BATTERY, "");
|
||||
res = get_belkin_reply(temp);
|
||||
if (res > 0) {
|
||||
/* report the compiled in battery charge where the driver assumes the battery is low */
|
||||
dstate_setinfo("battery.charge.low", "%d", LOW_BAT);
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 10);
|
||||
res = atoi(st);
|
||||
get_belkin_field(temp, st, sizeof(st), 2);
|
||||
|
||||
if (*st == '1' || res < LOW_BAT) {
|
||||
status_set("LB"); /* low battery */
|
||||
}
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 10);
|
||||
dstate_setinfo("battery.charge", "%.0f", strtod(st, NULL));
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 9);
|
||||
dstate_setinfo("battery.temperature", "%.0f", strtod(st, NULL));
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 7);
|
||||
dstate_setinfo("battery.voltage", "%.1f", strtod(st, NULL) / 10);
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 9);
|
||||
dstate_setinfo("ups.temperature", "%.0f", strtod(st, NULL));
|
||||
}
|
||||
|
||||
send_belkin_command(STATUS, STAT_INPUT, "");
|
||||
res = get_belkin_reply(temp);
|
||||
if (res > 0) {
|
||||
get_belkin_field(temp, st, sizeof(st), 3);
|
||||
dstate_setinfo("input.voltage", "%.1f", strtod(st, NULL) / 10);
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 2);
|
||||
dstate_setinfo("input.frequency", "%.1f", strtod(st, NULL) / 10);
|
||||
}
|
||||
|
||||
send_belkin_command(STATUS, STAT_OUTPUT, "");
|
||||
res = get_belkin_reply(temp);
|
||||
if (res > 0) {
|
||||
get_belkin_field(temp, st, sizeof(st), 2);
|
||||
dstate_setinfo("output.frequency", "%.1f", strtod(st, NULL) / 10);
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 4);
|
||||
dstate_setinfo("output.voltage", "%.1f", strtod(st, NULL) / 10);
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 7);
|
||||
dstate_setinfo("ups.load", "%.0f", strtod(st, NULL));
|
||||
}
|
||||
|
||||
send_belkin_command(STATUS, TEST_RESULT, "");
|
||||
res = get_belkin_reply(temp);
|
||||
if (res > 0) {
|
||||
get_belkin_field(temp, st, sizeof(st), 1);
|
||||
switch (*st)
|
||||
{
|
||||
case '0':
|
||||
dstate_setinfo("ups.test.result", "%s", "No test performed");
|
||||
break;
|
||||
|
||||
case '1':
|
||||
dstate_setinfo("ups.test.result", "%s", "Passed");
|
||||
break;
|
||||
|
||||
case '2':
|
||||
dstate_setinfo("ups.test.result", "%s", "In progress");
|
||||
break;
|
||||
|
||||
case '3':
|
||||
case '4':
|
||||
dstate_setinfo("ups.test.result", "%s", "10s test failed");
|
||||
break;
|
||||
|
||||
case '5':
|
||||
dstate_setinfo("ups.test.result", "%s", "deep test failed");
|
||||
break;
|
||||
|
||||
case '6':
|
||||
dstate_setinfo("ups.test.result", "%s", "Aborted");
|
||||
break;
|
||||
|
||||
default:
|
||||
upsdebugx(3, "Unhandled test status '%c'", *st);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
status_commit();
|
||||
|
||||
dstate_dataok();
|
||||
}
|
||||
|
||||
/* power down the attached load immediately */
|
||||
void upsdrv_shutdown(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = init_communication();
|
||||
if (res == -1)
|
||||
if (res < 0) {
|
||||
printf("Detection failed. Trying a shutdown command anyway.\n");
|
||||
}
|
||||
|
||||
/* tested on a F6C525-SER: this works when OL and OB */
|
||||
|
||||
|
|
@ -347,6 +369,27 @@ void upsdrv_shutdown(void)
|
|||
send_belkin_command(CONTROL, "SDA", "5");
|
||||
}
|
||||
|
||||
/* handle "beeper.disable" */
|
||||
static void do_beeper_off(void) {
|
||||
int res;
|
||||
char temp[SMALLBUF];
|
||||
const char *arg;
|
||||
|
||||
/* Compare the model name, as the BUZZER_OFF argument depends on it */
|
||||
send_belkin_command(STATUS, MODEL, "");
|
||||
res = get_belkin_reply(temp);
|
||||
if (res == -1)
|
||||
return;
|
||||
|
||||
if (!strcmp(temp, "F6C1400-EUR")) {
|
||||
arg = BUZZER_OFF2;
|
||||
} else {
|
||||
arg = BUZZER_OFF0;
|
||||
}
|
||||
|
||||
send_belkin_command(CONTROL,BUZZER,arg);
|
||||
}
|
||||
|
||||
/* handle the "load.off" with some paranoia */
|
||||
static void do_off(void)
|
||||
{
|
||||
|
|
@ -375,6 +418,16 @@ static void do_off(void)
|
|||
|
||||
static int instcmd(const char *cmdname, const char *extra)
|
||||
{
|
||||
if (!strcasecmp(cmdname, "beeper.disable")) {
|
||||
do_beeper_off();
|
||||
return STAT_INSTCMD_HANDLED;
|
||||
}
|
||||
|
||||
if (!strcasecmp(cmdname, "beeper.enable")) {
|
||||
send_belkin_command(CONTROL,BUZZER,BUZZER_ON);
|
||||
return STAT_INSTCMD_HANDLED;
|
||||
}
|
||||
|
||||
if (!strcasecmp(cmdname, "load.off")) {
|
||||
do_off();
|
||||
return STAT_INSTCMD_HANDLED;
|
||||
|
|
@ -385,17 +438,25 @@ static int instcmd(const char *cmdname, const char *extra)
|
|||
return STAT_INSTCMD_HANDLED;
|
||||
}
|
||||
|
||||
if (!strcasecmp(cmdname, "test.battery.start.quick")) {
|
||||
send_belkin_command(CONTROL,TEST,TEST_10SEC);
|
||||
return STAT_INSTCMD_HANDLED;
|
||||
}
|
||||
|
||||
if (!strcasecmp(cmdname, "test.battery.start.deep")) {
|
||||
send_belkin_command(CONTROL,TEST,TEST_DEEP);
|
||||
return STAT_INSTCMD_HANDLED;
|
||||
}
|
||||
|
||||
if (!strcasecmp(cmdname, "test.battery.stop")) {
|
||||
send_belkin_command(CONTROL,TEST,TEST_CANCEL);
|
||||
return STAT_INSTCMD_HANDLED;
|
||||
}
|
||||
|
||||
upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname);
|
||||
return STAT_INSTCMD_UNKNOWN;
|
||||
}
|
||||
|
||||
static void set_serialDTR0RTS1(void)
|
||||
{
|
||||
/* set DTR to low and RTS to high */
|
||||
ser_set_dtr(upsfd, 0);
|
||||
ser_set_rts(upsfd, 1);
|
||||
}
|
||||
|
||||
void upsdrv_help(void)
|
||||
{
|
||||
}
|
||||
|
|
@ -409,8 +470,10 @@ void upsdrv_initups(void)
|
|||
{
|
||||
upsfd = ser_open(device_path);
|
||||
ser_set_speed(upsfd, device_path, B2400);
|
||||
|
||||
set_serialDTR0RTS1();
|
||||
|
||||
/* set DTR to low and RTS to high */
|
||||
ser_set_dtr(upsfd, 0);
|
||||
ser_set_rts(upsfd, 1);
|
||||
|
||||
sleep(1);
|
||||
|
||||
|
|
@ -420,9 +483,10 @@ void upsdrv_initups(void)
|
|||
void upsdrv_initinfo(void)
|
||||
{
|
||||
int res;
|
||||
char temp[SMALLBUF], st[SMALLBUF];
|
||||
|
||||
res = init_communication();
|
||||
if (res == -1) {
|
||||
if (res < 0) {
|
||||
fatalx(EXIT_FAILURE,
|
||||
"Unable to detect an Belkin Smart protocol UPS on port %s\n"
|
||||
"Check the cabling, port name or model name and try again", device_path
|
||||
|
|
@ -431,11 +495,42 @@ void upsdrv_initinfo(void)
|
|||
|
||||
dstate_setinfo("ups.mfr", "BELKIN");
|
||||
|
||||
/* see what's out there */
|
||||
init_ups_data();
|
||||
send_belkin_command(STATUS, MODEL, "");
|
||||
res = get_belkin_reply(temp);
|
||||
if (res > 0) {
|
||||
dstate_setinfo("ups.model", "%s", temp);
|
||||
}
|
||||
|
||||
printf("Detected %s on %s\n", dstate_getinfo("ups.model"),
|
||||
device_path);
|
||||
send_belkin_command(STATUS, VERSION_CMD, "");
|
||||
res = get_belkin_reply(temp);
|
||||
if (res > 0) {
|
||||
dstate_setinfo("ups.firmware", "%s", temp);
|
||||
}
|
||||
|
||||
/* deal with stupid firmware that breaks RAT */
|
||||
send_belkin_command(STATUS, RATING, "");
|
||||
|
||||
if (!strcmp(temp, "001")) {
|
||||
res = do_broken_rat(temp);
|
||||
} else {
|
||||
res = get_belkin_reply(temp);
|
||||
}
|
||||
|
||||
if (res > 0) {
|
||||
get_belkin_field(temp, st, sizeof(st), 8);
|
||||
dstate_setinfo("input.transfer.low", "%.0f", strtod(st, NULL) / 0.88);
|
||||
|
||||
get_belkin_field(temp, st, sizeof(st), 9);
|
||||
dstate_setinfo("input.transfer.high", "%.0f", strtod(st, NULL) * 0.88);
|
||||
}
|
||||
|
||||
dstate_addcmd("beeper.disable");
|
||||
dstate_addcmd("beeper.enable");
|
||||
dstate_addcmd("load.off");
|
||||
dstate_addcmd("load.on");
|
||||
dstate_addcmd("test.battery.start.quick");
|
||||
dstate_addcmd("test.battery.start.deep");
|
||||
dstate_addcmd("test.battery.stop");
|
||||
|
||||
upsh.instcmd = instcmd;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue