void upsdrv_initinfo(void) { int msglen, v; char *a,*p,avail_list[300]; /* find out which variables/commands this UPS supports */ msglen = 0; sec_cmd(SEC_POLLCMD, SEC_AVAILP1, avail_list, &msglen); p = avail_list + msglen; if (p != avail_list) *p++ = ','; msglen = 0; sec_cmd(SEC_POLLCMD, SEC_AVAILP2, p, &msglen); *(p+msglen) = '\0'; if (strlen(avail_list) == 0){ fatalx(EXIT_FAILURE, "No available variables found!");} a = avail_list; while ((p = strtok(a, ",")) != NULL) { a = NULL; v = atoi(p); /* don't bother adding a write-only variable */ if (sec_varlist[v].flags == FLAG_WONLY) continue; addquery(sec_varlist[v].cmd, sec_varlist[v].field, v, sec_varlist[v].poll); } /* poll one time values */ sec_poll(FLAG_POLLONCE); printf("UPS: %s %s\n", dstate_getinfo("ups.mfr"), dstate_getinfo("ups.model")); }
/* write the status_buf into the externally visible dstate storage */ void status_commit(void) { while (ignorelb) { const char *val, *low; val = dstate_getinfo("battery.charge"); low = dstate_getinfo("battery.charge.low"); if (val && low && (strtol(val, NULL, 10) < strtol(low, NULL, 10))) { snprintfcat(status_buf, sizeof(status_buf), " LB"); upsdebugx(2, "%s: appending LB flag [charge '%s' below '%s']", __func__, val, low); break; } val = dstate_getinfo("battery.runtime"); low = dstate_getinfo("battery.runtime.low"); if (val && low && (strtol(val, NULL, 10) < strtol(low, NULL, 10))) { snprintfcat(status_buf, sizeof(status_buf), " LB"); upsdebugx(2, "%s: appending LB flag [runtime '%s' below '%s']", __func__, val, low); break; } /* LB condition not detected */ break; } if (alarm_active) { dstate_setinfo("ups.status", "ALARM %s", status_buf); } else { dstate_setinfo("ups.status", "%s", status_buf); } }
void upsdrv_initinfo(void) { dstate_setinfo("ups.mfr", "%s", "PACE"); dstate_setinfo("ups.model", "PACE %s", "UPS7"); printf("Detected %s %s on %s\n", dstate_getinfo("ups.mfr"), dstate_getinfo("ups.model"), device_path); }
int upsdrv_initups(void) { struct termios tio; const char *val; upsfd = ser_open(device_path); ser_set_speed(upsfd, device_path, B1200); if (tcgetattr(upsfd, &tio)) { fatal_with_errno(EXIT_FAILURE, "tcgetattr"); } /* * Use canonical mode input processing (to read reply line) */ tio.c_lflag |= ICANON; /* Canonical input (erase and kill processing) */ tio.c_iflag |= IGNCR; /* Ignore CR */ tio.c_iflag |= IGNBRK; /* Ignore break condition */ tio.c_oflag |= ONLCR; /* Map NL to CR-NL on output */ tio.c_cc[VEOF] = _POSIX_VDISABLE; tio.c_cc[VEOL] = _POSIX_VDISABLE; tio.c_cc[VERASE] = _POSIX_VDISABLE; tio.c_cc[VINTR] = _POSIX_VDISABLE; tio.c_cc[VKILL] = _POSIX_VDISABLE; tio.c_cc[VQUIT] = _POSIX_VDISABLE; tio.c_cc[VSUSP] = _POSIX_VDISABLE; tio.c_cc[VSTART] = _POSIX_VDISABLE; tio.c_cc[VSTOP] = _POSIX_VDISABLE; if (tcsetattr(upsfd, TCSANOW, &tio)) { fatal_with_errno(EXIT_FAILURE, "tcsetattr"); } /* * Set DTR and clear RTS to provide power for the serial interface. */ ser_set_dtr(upsfd, 1); ser_set_rts(upsfd, 0); val = dstate_getinfo("battery.voltage.nominal"); battery.voltage.nom = (val) ? strtod(val, NULL) : 12.00; val = dstate_getinfo("battery.voltage.low"); battery.voltage.low = (val) ? strtod(val, NULL) : 10.80; if (battery.voltage.nom <= battery.voltage.low) { fatalx(EXIT_FAILURE, "Nominal battery voltage must be higher than low battery voltage!"); } return 1; }
/* Set up all the funky shared memory stuff used to communicate with upsd */ void upsdrv_initinfo (void) { /* now set up room for all future variables that are supported */ dstate_setinfo("ups.mfr", "%s", "Best Power"); switch(fc.model) { case ME3100: dstate_setinfo("ups.model", "Micro Ferrups (ME) %d", fc.va); break; case MD1KVA: dstate_setinfo("ups.model", "Micro Ferrups (MD) %d", fc.va); break; case RE1800: dstate_setinfo("ups.model", "Micro Ferrups (RE) %d", fc.va); break; default: fatalx(EXIT_FAILURE, "UPS model not matched!"); /* Will never get here, upsdrv_initups() will catch */ } fprintf(stderr, "Best Power %s detected\n", dstate_getinfo("ups.model")); fprintf(stderr, "Battery voltages %5.1f nominal, %5.1f full, %5.1f empty\n", fc.idealbvolts, fc.fullvolts, fc.emptyvolts); }
/* * The battery voltage will quickly return to at least the nominal value after * discharging them. For overlapping battery.voltage.low/high ranges therefor * choose the one with the highest multiplier. */ static double blazer_packs(const char *ptr, char **endptr) { const double packs[] = { 120, 100, 80, 60, 48, 36, 30, 24, 18, 12, 8, 6, 4, 3, 2, 1, 0.5, -1 }; const char *val; int i; val = dstate_getinfo("battery.voltage.nominal"); batt.volt.nom = strtod(val ? val : ptr, endptr); for (i = 0; packs[i] > 0; i++) { if (packs[i] * batt.volt.act > 1.2 * batt.volt.nom) { continue; } if (packs[i] * batt.volt.act < 0.8 * batt.volt.nom) { upslogx(LOG_INFO, "Can't autodetect number of battery packs [%.0f/%.2f]", batt.volt.nom, batt.volt.act); break; } batt.packs = packs[i]; break; } return batt.volt.nom; }
/* Change a variable name in a table */ static void change_name(simple_t *sp, const char *oldname, const char *newname) { while(sp->code) { if (sp->desc && !strcmp(sp->desc, oldname)) { sp->desc = strdup(newname); if (dstate_getinfo(oldname)) { dstate_setinfo(newname, "%s", dstate_getinfo(oldname)); } dstate_delinfo(oldname); upsdebugx(1, "Changing name: %s => %s", oldname, newname); break; } sp++; } }
/* clean out the temp space for a new pass */ void status_init(void) { if (dstate_getinfo("driver.flag.ignorelb")) { ignorelb = 1; } memset(status_buf, 0, sizeof(status_buf)); }
void blazer_initups(void) { const char *val; val = getval("ondelay"); if (val) { ondelay = strtol(val, NULL, 10); } if ((ondelay < 0) || (ondelay > 9999)) { fatalx(EXIT_FAILURE, "Start delay '%d' out of range [0..9999]", ondelay); } val = getval("offdelay"); if (val) { offdelay = strtol(val, NULL, 10); } if ((offdelay < 12) || (offdelay > 600)) { fatalx(EXIT_FAILURE, "Shutdown delay '%d' out of range [12..600]", offdelay); } /* Truncate to nearest setable value */ if (offdelay < 60) { offdelay -= (offdelay % 6); } else { offdelay -= (offdelay % 60); } val = dstate_getinfo("battery.voltage.high"); if (val) { batt.volt.high = strtod(val, NULL); } val = dstate_getinfo("battery.voltage.low"); if (val) { batt.volt.low = strtod(val, NULL); } }
/* returns statically allocated string - must not use it again before done with result! */ static const char *tripplite_chemistry_fun(double value) { static char buf[20]; const char *model; model = dstate_getinfo("ups.productid"); /* Workaround for AVR 550U firmware bug */ if (!strcmp(model, "1003")) { return "unknown"; } /* Workaround for OMNI1000LCD firmware bug */ if (!strcmp(model, "2005")) { return "unknown"; } return HIDGetIndexString(udev, (int)value, buf, sizeof(buf)); }
/* * Do whatever we think is needed when we read a battery voltage from the UPS. * Basically all it does now, is guestimating the battery charge, but this * could be extended. */ static double blazer_battery(const char *ptr, char **endptr) { batt.volt.act = batt.packs * strtod(ptr, endptr); if ((!getval("runtimecal") || !dstate_getinfo("battery.charge")) && (batt.volt.low > 0) && (batt.volt.high > batt.volt.low)) { batt.chrg.act = 100 * (batt.volt.act - batt.volt.low) / (batt.volt.high - batt.volt.low); if (batt.chrg.act < 0) { batt.chrg.act = 0; } if (batt.chrg.act > 100) { batt.chrg.act = 100; } dstate_setinfo("battery.charge", "%.0f", batt.chrg.act); } return batt.volt.act; }
static int instcmd(const char *cmdname, const char *extra) { const char *val; val = dstate_getinfo(getval("load.status")); if (val) { if (!strcasecmp(val, "off") || !strcasecmp(val, "no")) { outlet = 0; } if (!strcasecmp(val, "on") || !strcasecmp(val, "yes")) { outlet = 1; } } if (!strcasecmp(cmdname, "shutdown.return")) { if (outlet && (ups.timer.shutdown < 0)) { ups.timer.shutdown = offdelay; dstate_setinfo("ups.status", "FSD %s", ups.status); } ups.timer.start = ondelay; return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "shutdown.stayoff")) { if (outlet && (ups.timer.shutdown < 0)) { ups.timer.shutdown = offdelay; dstate_setinfo("ups.status", "FSD %s", ups.status); } ups.timer.start = -1; return STAT_INSTCMD_HANDLED; } upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname); return STAT_INSTCMD_UNKNOWN; }
static void blazer_initbattery(void) { const char *val; /* If no values were provided by the user in ups.conf, try to guesstimate * battery.charge, but announce it! */ if ((batt.volt.nom != 1) && ((batt.volt.high == -1) || (batt.volt.low == -1))) { upslogx(LOG_INFO, "No values provided for battery high/low voltages in ups.conf\n"); /* Basic formula, which should cover most cases */ batt.volt.low = 104 * batt.volt.nom / 120; batt.volt.high = 130 * batt.volt.nom / 120; /* Publish these data too */ dstate_setinfo("battery.voltage.low", "%.2f", batt.volt.low); dstate_setinfo("battery.voltage.high", "%.2f", batt.volt.high); upslogx(LOG_INFO, "Using 'guestimation' (low: %f, high: %f)!", batt.volt.low, batt.volt.high); } val = getval("runtimecal"); if (val) { double rh, lh, rl, ll; time(&lastpoll); if (sscanf(val, "%lf,%lf,%lf,%lf", &rh, &lh, &rl, &ll) < 4) { fatalx(EXIT_FAILURE, "Insufficient parameters for runtimecal"); } if ((rl < rh) || (rh <= 0)) { fatalx(EXIT_FAILURE, "Parameter out of range (runtime)"); } if ((lh > 100) || (ll > lh) || (ll <= 0)) { fatalx(EXIT_FAILURE, "Parameter out of range (load)"); } batt.runt.exp = log(rl / rh) / log(lh / ll); upsdebugx(2, "battery runtime exponent : %.3f", batt.runt.exp); batt.runt.nom = rh * pow(lh / 100, batt.runt.exp); upsdebugx(2, "battery runtime nominal : %.1f", batt.runt.nom); } else { upslogx(LOG_INFO, "Battery runtime will not be calculated (runtimecal not set)"); return; } if (batt.chrg.act < 0) { batt.volt.low = batt.volt.nom; batt.volt.high = 1.15 * batt.volt.nom; blazer_battery(dstate_getinfo("battery.voltage"), NULL); } val = dstate_getinfo("battery.charge"); if (val) { batt.runt.est = batt.runt.nom * strtod(val, NULL) / 100; upsdebugx(2, "battery runtime estimate : %.1f", batt.runt.est); } else { fatalx(EXIT_FAILURE, "Initial battery charge undetermined"); } val = getval("chargetime"); if (val) { batt.chrg.time = strtol(val, NULL, 10); if (batt.chrg.time <= 0) { fatalx(EXIT_FAILURE, "Charge time out of range [1..s]"); } upsdebugx(2, "battery charge time : %ld", batt.chrg.time); } else { upslogx(LOG_INFO, "No charge time specified, using built in default [%ld seconds]", batt.chrg.time); } val = getval("idleload"); if (val) { load.low = strtod(val, NULL) / 100; if ((load.low <= 0) || (load.low > 1)) { fatalx(EXIT_FAILURE, "Idle load out of range [0..100]"); } upsdebugx(2, "minimum load used (idle) : %.3f", load.low); } else { upslogx(LOG_INFO, "No idle load specified, using built in default [%.1f %%]", 100 * load.low); } }
static int blazer_status(const char *cmd) { const struct { const char *var; const char *fmt; double (*conv)(const char *, char **); } status[] = { { "input.voltage", "%.1f", strtod }, { "input.voltage.fault", "%.1f", strtod }, { "output.voltage", "%.1f", strtod }, { "ups.load", "%.0f", blazer_load }, { "input.frequency", "%.1f", strtod }, { "battery.voltage", "%.2f", blazer_battery }, { "ups.temperature", "%.1f", strtod }, { NULL } }; char buf[SMALLBUF], *val, *last = NULL; int i; /* * > [Q1\r] * < [(226.0 195.0 226.0 014 49.0 27.5 30.0 00001000\r] * 01234567890123456789012345678901234567890123456 * 0 1 2 3 4 */ if (blazer_command(cmd, buf, sizeof(buf)) < 46) { upsdebugx(2, "%s: short reply", __func__); return -1; } if (buf[0] != '(') { upsdebugx(2, "%s: invalid start character [%02x]", __func__, buf[0]); return -1; } for (i = 0, val = strtok_r(buf+1, " ", &last); status[i].var; i++, val = strtok_r(NULL, " \r\n", &last)) { if (!val) { upsdebugx(2, "%s: parsing failed", __func__); return -1; } if (strspn(val, "0123456789.") != strlen(val)) { upsdebugx(2, "%s: non numerical value [%s]", __func__, val); continue; } dstate_setinfo(status[i].var, status[i].fmt, status[i].conv(val, NULL)); } if (!val) { upsdebugx(2, "%s: parsing failed", __func__); return -1; } if (strspn(val, "01") != 8) { upsdebugx(2, "Invalid status [%s]", val); return -1; } if (val[7] == '1') { /* Beeper On */ dstate_setinfo("ups.beeper.status", "enabled"); } else { dstate_setinfo("ups.beeper.status", "disabled"); } if (val[4] == '1') { /* UPS Type is Standby (0 is On_line) */ dstate_setinfo("ups.type", "offline / line interactive"); } else { dstate_setinfo("ups.type", "online"); } status_init(); if (val[0] == '1') { /* Utility Fail (Immediate) */ status_set("OB"); online = 0; } else { status_set("OL"); online = 1; } if (val[1] == '1') { /* Battery Low */ status_set("LB"); } if (val[2] == '1') { /* Bypass/Boost or Buck Active */ double vi, vo; vi = strtod(dstate_getinfo("input.voltage"), NULL); vo = strtod(dstate_getinfo("output.voltage"), NULL); if (vo < 0.5 * vi) { upsdebugx(2, "%s: output voltage too low", __func__); } else if (vo < 0.95 * vi) { status_set("TRIM"); } else if (vo < 1.05 * vi) { status_set("BYPASS"); } else if (vo < 1.5 * vi) { status_set("BOOST"); } else { upsdebugx(2, "%s: output voltage too high", __func__); } } if (val[5] == '1') { /* Test in Progress */ status_set("CAL"); } alarm_init(); if (val[3] == '1') { /* UPS Failed */ alarm_set("UPS selftest failed!"); } if (val[6] == '1') { /* Shutdown Active */ alarm_set("Shutdown imminent!"); status_set("FSD"); } alarm_commit(); status_commit(); return 0; }
void upsdrv_initinfo(void) { unsigned char my_answer[255]; char serial[13]; int res, i; /* Initial setup of variables */ #ifdef EXTRADATA dstate_setinfo("output.power", "%d", -1); dstate_setflags("output.power", ST_FLAG_RW); #endif dstate_setinfo("output.voltage", "%d", -1); dstate_setflags("output.voltage", ST_FLAG_RW); dstate_setinfo("output.current", "%d", -1); dstate_setflags("output.current", ST_FLAG_RW); #ifdef EXTRADATA dstate_setinfo("output.current.peak", "%2.2f", -1); dstate_setflags("output.current.peak", ST_FLAG_RW); dstate_setinfo("input.power", "%d", -1); dstate_setflags("input.power", ST_FLAG_RW); #endif dstate_setinfo("input.voltage", "%d", -1); dstate_setflags("input.voltage", ST_FLAG_RW); #ifdef EXTRADATA dstate_setinfo("input.current", "%2.2f", -1); dstate_setflags("input.current", ST_FLAG_RW); dstate_setinfo("input.current.peak", "%2.2f", -1); dstate_setflags("input.current.peak", ST_FLAG_RW); #endif dstate_setinfo("battery.voltage", "%d", -1); dstate_setflags("battery.voltage", ST_FLAG_RW); #ifdef EXTRADATA dstate_setinfo("battery.voltage.low", "%2.2f", -1); dstate_setflags("battery.voltage.low", ST_FLAG_RW); dstate_setinfo("battery.voltage.exhaust", "%2.2f", -1); dstate_setflags("battery.voltage.exhaust", ST_FLAG_RW); dstate_setinfo("ups.total.runtime", "retrieving..."); dstate_setflags("ups.total.runtime", ST_FLAG_STRING | ST_FLAG_RW); dstate_setaux("ups.total.runtime", 20); dstate_setinfo("ups.inverter.runtime", "retrieving..."); dstate_setflags("ups.inverter.runtime", ST_FLAG_STRING | ST_FLAG_RW); dstate_setaux("ups.inverter.runtime", 20); dstate_setinfo("ups.inverter.interventions", "%d", -1); dstate_setflags("ups.inverter.interventions", ST_FLAG_RW); dstate_setinfo("battery.full.discharges", "%d", -1); dstate_setflags("battery.full.discharges", ST_FLAG_RW); dstate_setinfo("ups.bypass.interventions", "%d", -1); dstate_setflags("ups.bypass.interventions", ST_FLAG_RW); dstate_setinfo("ups.overheatings", "%d", -1); dstate_setflags("ups.overheatings", ST_FLAG_RW); #endif dstate_setinfo("ups.load", "%d", -1); dstate_setflags("ups.load", ST_FLAG_RW); dstate_setinfo("ups.delay.shutdown", "%d", -1); dstate_setflags("ups.delay.shutdown", ST_FLAG_RW); dstate_setinfo("ups.delay.start", "%d", -1); dstate_setflags("ups.delay.start", ST_FLAG_RW); dstate_setinfo("ups.temperature", "%d", -1); dstate_setflags("ups.temperature", ST_FLAG_RW); dstate_setinfo("ups.test.result", "not yet done..."); dstate_setflags("ups.test.result", ST_FLAG_STRING | ST_FLAG_RW); dstate_setaux("ups.test.result", 20); /* UPS INFO READ */ res = command_read_sequence(UPS_INFO, my_answer); if (res < 0) fatal_with_errno(EXIT_FAILURE, "Could not communicate with the ups"); /* the manufacturer is hard coded into the driver, the model type is in the second byte of the answer, the third byte identifies the model version */ dstate_setinfo("ups.mfr", "Meta System"); i = my_answer[1] * 10 + my_answer[2]; switch (i) { case 11: dstate_setinfo("ups.model", "%s", "HF Line (1 board)"); nominal_power = 630; break; case 12: dstate_setinfo("ups.model", "%s", "HF Line (2 boards)"); nominal_power = 1260; break; case 13: dstate_setinfo("ups.model", "%s", "HF Line (3 boards)"); nominal_power = 1890; break; case 14: dstate_setinfo("ups.model", "%s", "HF Line (4 boards)"); nominal_power = 2520; break; case 21: dstate_setinfo("ups.model", "%s", "ECO Network 750/1000"); nominal_power = 500; break; case 22: dstate_setinfo("ups.model", "%s", "ECO Network 1050/1500"); nominal_power = 700; break; case 23: dstate_setinfo("ups.model", "%s", "ECO Network 1500/2000"); nominal_power = 1000; break; case 24: dstate_setinfo("ups.model", "%s", "ECO Network 1800/2500"); nominal_power = 1200; break; case 25: dstate_setinfo("ups.model", "%s", "ECO Network 2100/3000"); nominal_power = 1400; break; case 31: dstate_setinfo("ups.model", "%s", "ECO 308"); nominal_power = 500; break; case 32: dstate_setinfo("ups.model", "%s", "ECO 311"); nominal_power = 700; break; case 44: dstate_setinfo("ups.model", "%s", "HF Line (4 boards)/2"); nominal_power = 2520; break; case 45: dstate_setinfo("ups.model", "%s", "HF Line (5 boards)/2"); nominal_power = 3150; break; case 46: dstate_setinfo("ups.model", "%s", "HF Line (6 boards)/2"); nominal_power = 3780; break; case 47: dstate_setinfo("ups.model", "%s", "HF Line (7 boards)/2"); nominal_power = 4410; break; case 48: dstate_setinfo("ups.model", "%s", "HF Line (8 boards)/2"); nominal_power = 5040; break; case 51: dstate_setinfo("ups.model", "%s", "HF Millennium 810"); nominal_power = 700; break; case 52: dstate_setinfo("ups.model", "%s", "HF Millennium 820"); nominal_power = 1400; break; case 61: dstate_setinfo("ups.model", "%s", "HF TOP Line 910"); nominal_power = 700; break; case 62: dstate_setinfo("ups.model", "%s", "HF TOP Line 920"); nominal_power = 1400; break; case 63: dstate_setinfo("ups.model", "%s", "HF TOP Line 930"); nominal_power = 2100; break; case 64: dstate_setinfo("ups.model", "%s", "HF TOP Line 940"); nominal_power = 2800; break; case 74: dstate_setinfo("ups.model", "%s", "HF TOP Line 940/2"); nominal_power = 2800; break; case 75: dstate_setinfo("ups.model", "%s", "HF TOP Line 950/2"); nominal_power = 3500; break; case 76: dstate_setinfo("ups.model", "%s", "HF TOP Line 960/2"); nominal_power = 4200; break; case 77: dstate_setinfo("ups.model", "%s", "HF TOP Line 970/2"); nominal_power = 4900; break; case 78: dstate_setinfo("ups.model", "%s", "HF TOP Line 980/2"); nominal_power = 5600; break; case 81: dstate_setinfo("ups.model", "%s", "ECO 508"); nominal_power = 500; break; case 82: dstate_setinfo("ups.model", "%s", "ECO 511"); nominal_power = 700; break; case 83: dstate_setinfo("ups.model", "%s", "ECO 516"); nominal_power = 1000; break; case 84: dstate_setinfo("ups.model", "%s", "ECO 519"); nominal_power = 1200; break; case 85: dstate_setinfo("ups.model", "%s", "ECO 522"); nominal_power = 1400; break; case 91: dstate_setinfo("ups.model", "%s", "ECO 305 / Harviot 530 SX"); nominal_power = 330; break; case 92: dstate_setinfo("ups.model", "%s", "ORDINATORE 2"); nominal_power = 330; break; case 93: dstate_setinfo("ups.model", "%s", "Harviot 730 SX"); nominal_power = 430; break; case 101: dstate_setinfo("ups.model", "%s", "ECO 308 SX / SX Interactive / Ordinatore"); nominal_power = 500; break; case 102: dstate_setinfo("ups.model", "%s", "ECO 311 SX / SX Interactive"); nominal_power = 700; break; case 111: dstate_setinfo("ups.model", "%s", "ally HF 800 / BI-TWICE 800"); nominal_power = 560; break; case 112: dstate_setinfo("ups.model", "%s", "ally HF 1600"); nominal_power = 1120; break; case 121: dstate_setinfo("ups.model", "%s", "ally HF 1000 / BI-TWICE 1000"); nominal_power = 700; break; case 122: dstate_setinfo("ups.model", "%s", "ally HF 2000"); nominal_power = 1400; break; case 131: dstate_setinfo("ups.model", "%s", "ally HF 1250 / BI-TWICE 1250"); nominal_power = 875; break; case 132: dstate_setinfo("ups.model", "%s", "ally HF 2500"); nominal_power = 1750; break; case 141: dstate_setinfo("ups.model", "%s", "Megaline 1250"); nominal_power = 875; break; case 142: dstate_setinfo("ups.model", "%s", "Megaline 2500"); nominal_power = 1750; break; case 143: dstate_setinfo("ups.model", "%s", "Megaline 3750"); nominal_power = 2625; break; case 144: dstate_setinfo("ups.model", "%s", "Megaline 5000"); nominal_power = 3500; break; case 154: dstate_setinfo("ups.model", "%s", "Megaline 5000 / 2"); nominal_power = 3500; break; case 155: dstate_setinfo("ups.model", "%s", "Megaline 6250 / 2"); nominal_power = 4375; break; case 156: dstate_setinfo("ups.model", "%s", "Megaline 7500 / 2"); nominal_power = 5250; break; case 157: dstate_setinfo("ups.model", "%s", "Megaline 8750 / 2"); nominal_power = 6125; break; case 158: dstate_setinfo("ups.model", "%s", "Megaline 10000 / 2"); nominal_power = 7000; break; default: fatal_with_errno(EXIT_FAILURE, "Unknown UPS"); break; } /* Get the serial number */ memcpy(serial, my_answer + 7, res - 7); /* serial number start from the 8th byte */ serial[12]=0; /* terminate string */ dstate_setinfo("ups.serial", "%s", serial); /* get the ups firmware. The major number is in the 5th byte, the minor is in the 6th */ dstate_setinfo("ups.firmware", "%u.%u", my_answer[5], my_answer[6]); printf("Detected %s [%s] v.%s on %s\n", dstate_getinfo("ups.model"), dstate_getinfo("ups.serial"), dstate_getinfo("ups.firmware"), device_path); /* Add instant commands */ dstate_addcmd("shutdown.return"); dstate_addcmd("shutdown.stayoff"); dstate_addcmd("shutdown.stop"); dstate_addcmd("test.failure.start"); dstate_addcmd("test.failure.stop"); dstate_addcmd("test.battery.start"); dstate_addcmd("beeper.enable"); dstate_addcmd("beeper.mute"); dstate_addcmd("beeper.on"); dstate_addcmd("beeper.off"); upsh.instcmd = instcmd; return; }
void upsdrv_updateinfo(void) { typedef struct { const unsigned char cmd[6]; const char *var; const char *fmt; const int multindex; } cmd_s; static cmd_s vartab[] = { /* common vars */ { { 1,149,2,1,1,154 }, "battery.runtime", "%.0f", M_BAT_RUNTIME }, { { 1,149,2,1,2,155 }, "battery.voltage", "%.1f", M_VOLT_DC }, { { 1,149,2,1,3,156 }, "battery.current", "%.2f", M_CURRENT_DC }, { { 1,161,2,1,13,178 }, "battery.voltage.nominal", "%.1f", M_VOLT_DC }, { { 1,149,2,1,12,165 }, "battery.temperature", "%.1f", M_TEMPERATURE }, { { 1,149,2,1,14,167 }, "ups.temperature", "%.1f", M_TEMPERATURE }, { { 1,161,2,1,8,173 }, "ups.power.nominal", "%.0f", M_NOMPOWER }, { { 1,161,2,1,4,169 }, "ups.delay.start", "%.0f", M_10 }, { { 1,161,2,1,14,179 },"battery.runtime.low", "%.0f", M_BAT_RUNTIME }, { { 1,149,2,1,8,161 }, "input.frequency", "%.1f", M_FREQUENCY }, { { 1,149,2,1,10,163 }, "input.bypass.frequency", "%.1f", M_FREQUENCY }, { { 1,161,2,1,9,174 }, "input.frequency.nominal", "%.1f", M_FREQUENCY }, { { 1,149,2,1,9,162 }, "output.frequency", "%.1f", M_FREQUENCY }, { { 1,161,2,1,10,175 }, "output.frequency.nominal", "%.1f", M_FREQUENCY }, { { 0 }, NULL, NULL, 0 } }; static cmd_s vartab1o[] = { /* 1-phase out */ { { 1,149,2,1,7,160 }, "ups.load", "%.0f", M_LOADPERC }, { { 1,149,2,1,6,159 }, "ups.power", "%.0f", M_POWER }, { { 1,149,2,1,5,158 }, "ups.realpower", "%.0f", M_POWER }, { { 1,144,2,1,3,151 }, "output.voltage", "%.1f", M_VOLTAGE_O }, { { 1,144,2,1,4,152 }, "output.current", "%.1f", M_CURRENT_O }, { { 0 }, NULL, NULL, 0 } }; static cmd_s vartab1i[] = { /* 1-phase in*/ { { 1,144,2,1,1,149 }, "input.voltage", "%.1f", M_VOLTAGE_I }, { { 1,144,2,1,5,153 }, "input.bypass.voltage", "%.1f", M_VOLTAGE_B }, { { 1,144,2,1,6,154 }, "input.bypass.current", "%.1f", M_CURRENT_B }, { { 0 }, NULL, NULL, 0 } }; static cmd_s vartab3o[] = { /*3-phase out */ { { 1,144,2,1,24,172 }, "ups.L1.load", "%.0f", M_LOADPERC }, { { 1,145,2,1,24,173 }, "ups.L2.load", "%.0f", M_LOADPERC }, { { 1,146,2,1,24,174 }, "ups.L3.load", "%.0f", M_LOADPERC }, { { 1,144,2,1,22,170 }, "ups.L1.power", "%.0f", M_POWER }, { { 1,145,2,1,22,171 }, "ups.L2.power", "%.0f", M_POWER }, { { 1,146,2,1,22,172 }, "ups.L3.power", "%.0f", M_POWER }, { { 1,144,2,1,21,169 }, "ups.L1.realpower", "%.0f", M_POWER }, { { 1,145,2,1,21,170 }, "ups.L2.realpower", "%.0f", M_POWER }, { { 1,146,2,1,21,171 }, "ups.L3.realpower", "%.0f", M_POWER }, { { 1,144,2,1,3,151 }, "output.L1-N.voltage", "%.1f", M_VOLTAGE_O }, { { 1,145,2,1,3,152 }, "output.L2-N.voltage", "%.1f", M_VOLTAGE_O }, { { 1,146,2,1,3,153 }, "output.L3-N.voltage", "%.1f", M_VOLTAGE_O }, { { 1,144,2,1,14,162 }, "output.L1.crestfactor", "%.1f", M_0_1 }, { { 1,145,2,1,14,163 }, "output.L2.crestfactor", "%.1f", M_0_1 }, { { 1,146,2,1,14,164 }, "output.L3.crestfactor", "%.1f", M_0_1 }, { { 0 }, NULL, NULL, 0 } }; static cmd_s vartab3i[] = { /*3-phase in */ { { 1,144,2,1,1,149 }, "input.L1-N.voltage", "%.1f", M_VOLTAGE_I }, { { 1,145,2,1,1,150 }, "input.L2-N.voltage", "%.1f", M_VOLTAGE_I }, { { 1,146,2,1,1,151 }, "input.L3-N.voltage", "%.1f", M_VOLTAGE_I }, { { 1,144,2,1,5,153 }, "input.L1-N.bypass.voltage", "%.1f", M_VOLTAGE_B }, { { 1,145,2,1,5,154 }, "input.L2-N.bypass.voltage", "%.1f", M_VOLTAGE_B }, { { 1,146,2,1,5,155 }, "input.L3-N.bypass.voltage", "%.1f", M_VOLTAGE_B }, { { 1,144,2,1,6,154 }, "input.L1-N.bypass.current", "%.1f", M_CURRENT_B }, { { 1,145,2,1,6,155 }, "input.L2-N.bypass.current", "%.1f", M_CURRENT_B }, { { 1,146,2,1,6,156 }, "input.L3-N.bypass.current", "%.1f", M_CURRENT_B }, { { 1,144,2,1,2,150 }, "input.L1.current", "%.1f", M_CURRENT_I }, { { 1,145,2,1,2,151 }, "input.L2.current", "%.1f", M_CURRENT_I }, { { 1,146,2,1,2,152 }, "input.L3.current", "%.1f", M_CURRENT_I }, { { 0 }, NULL, NULL, 0 } }; static cmd_s * cmdin_p; static cmd_s * cmdout_p; const char *val; char reply[8]; int ret, i; for (i = 0; vartab[i].var; i++) { int16_t val; ret = do_command(vartab[i].cmd, reply, 6); if (ret < 8) { continue; } val = (unsigned char)reply[5]; val <<= 8; val += (unsigned char)reply[6]; dstate_setinfo(vartab[i].var, vartab[i].fmt, val * multi[vartab[i].multindex]); } if (num_inphases>1){ cmdin_p=vartab3i; } else { cmdin_p=vartab1i; } if (num_outphases>1){ cmdout_p=vartab3o; } else { cmdout_p=vartab1o; } for (i = 0; cmdin_p[i].var; i++) { int16_t val; ret = do_command(cmdin_p[i].cmd, reply, 6); if (ret < 8) { continue; } val = (unsigned char)reply[5]; val <<= 8; val += (unsigned char)reply[6]; dstate_setinfo(cmdin_p[i].var, cmdin_p[i].fmt, val * multi[cmdin_p[i].multindex]); } for (i = 0; cmdout_p[i].var; i++) { int16_t val; ret = do_command(cmdout_p[i].cmd, reply, 6); if (ret < 8) { continue; } val = (unsigned char)reply[5]; val <<= 8; val += (unsigned char)reply[6]; dstate_setinfo(cmdout_p[i].var, cmdout_p[i].fmt, val * multi[cmdout_p[i].multindex]); } status_init(); ret = do_command(cmd_bitfield1, reply, 6); if (ret < 8) { upslogx(LOG_ERR, "Failed reading bitfield #1"); dstate_datastale(); return; } if (reply[5] & (1<<0)) { /* ON_BATTERY */ status_set("OB"); } else { status_set("OL"); } val = dstate_getinfo("battery.current"); if (val) { if (atof(val) > 0.05) { status_set("CHRG"); } if (atof(val) < -0.05) { status_set("DISCHRG"); } } ret = do_command(cmd_bitfield2, reply, 6); if (ret < 8) { upslogx(LOG_ERR, "Failed reading bitfield #2"); dstate_datastale(); return; } if (reply[6] & (1<<0)) { /* ON_BYPASS */ status_set("BYPASS"); } if (reply[6] & (1<<5)) { /* REPLACE_BATTERY */ status_set("RB"); } if (reply[6] & (1<<6)) { /* BOOST_ON */ status_set("BOOST"); } if (reply[5] & (1<<1)) { /* BUCK_ON */ status_set("TRIM"); } ret = do_command(cmd_bitfield3, reply, 6); if (ret < 8) { upslogx(LOG_ERR, "Failed reading bitfield #3"); dstate_datastale(); return; } if (reply[6] & (1<<0) ) { /* UPS_OVERLOAD */ status_set("OVER"); } if (reply[6] & (1<<5) ) { /* LOW_BATTERY */ status_set("LB"); } status_commit(); dstate_dataok(); }
/* Preprocess instant commands */ int blazer_process_command(item_t *item, char *value, const size_t valuelen) { if (!strcasecmp(item->info_type, "shutdown.return")) { /* Sn: Shutdown after n minutes and then turn on when mains is back * SnRm: Shutdown after n minutes and then turn on after m minutes * Accepted values for n: .2 -> .9 , 01 -> 10 * Accepted values for m: 0001 -> 9999 * Note: "S01R0001" and "S01R0002" may not work on early (GE) firmware versions. * The failure mode is that the UPS turns off and never returns. * The fix is to push the return value up by 2, i.e. S01R0003, and it will return online properly. * (thus the default of ondelay=3 mins) */ int offdelay = strtol(dstate_getinfo("ups.delay.shutdown"), NULL, 10), ondelay = strtol(dstate_getinfo("ups.delay.start"), NULL, 10) / 60; char buf[SMALLBUF] = ""; if (ondelay == 0) { if (offdelay < 60) { snprintf(buf, sizeof(buf), ".%d", offdelay / 6); } else { snprintf(buf, sizeof(buf), "%02d", offdelay / 60); } } else if (offdelay < 60) { snprintf(buf, sizeof(buf), ".%dR%04d", offdelay / 6, ondelay); } else { snprintf(buf, sizeof(buf), "%02dR%04d", offdelay / 60, ondelay); } snprintf(value, valuelen, item->command, buf); } else if (!strcasecmp(item->info_type, "shutdown.stayoff")) { /* SnR0000 * Shutdown after n minutes and stay off * Accepted values for n: .2 -> .9 , 01 -> 10 */ int offdelay = strtol(dstate_getinfo("ups.delay.shutdown"), NULL, 10); char buf[SMALLBUF] = ""; if (offdelay < 60) { snprintf(buf, sizeof(buf), ".%d", offdelay / 6); } else { snprintf(buf, sizeof(buf), "%02d", offdelay / 60); } snprintf(value, valuelen, item->command, buf); } else if (!strcasecmp(item->info_type, "test.battery.start")) { int delay = strlen(value) > 0 ? strtol(value, NULL, 10) : 600; if ((delay < 60) || (delay > 5940)) { upslogx(LOG_ERR, "%s: battery test time '%d' out of range [60..5940] seconds", item->info_type, delay); return -1; } delay = delay / 60; snprintf(value, valuelen, item->command, delay); } else { /* Don't know what happened */ return -1; } return 0; }
void upsdrv_updateinfo(void) { time_t now; int ok; float load; if (status & UPSC_STAT_NOTINIT) { upsdrv_initinfo(); } if (status & UPSC_STAT_NOTINIT) { return; } status = 0; ok = upsc_getparams("UPDS", simple); time(&now); if (ok && now - last_full > full_update_timer) { last_full = now; ok = upsc_getparams("UPDV", nominal); if (ok && can_upbs) ok = upsc_getparams("UPBS", battery); } if (!ok) { dstate_datastale(); last_full = 0; return; } if (!inited_phaseinfo) { if (dstate_getinfo("input.L3-L1.voltage") || dstate_getinfo("input.L3-N.voltage")) { num_inphases = 3; change_name(simple, "input.current", "input.L1.current"); change_name(simple, "input.realpower", "input.L1.realpower"); change_name(simple, "input.power", "input.L1.power"); change_name(simple, "input.voltage", "input.L1-N.voltage"); } if (dstate_getinfo("output.L3-L1.voltage") || dstate_getinfo("output.L3-N.voltage")) { const char *s; num_outphases = 3; if ((s=dstate_getinfo("ups.model")) && (!strncmp(s, "UPS9075", 7) || !strncmp(s, "UPS9100", 7) || !strncmp(s, "UPS9150", 7) || !strncmp(s, "UPS9200", 7) || !strncmp(s, "UPS9250", 7) || !strncmp(s, "UPS9300", 7) || !strncmp(s, "UPS9400", 7) || !strncmp(s, "UPS9500", 7) || !strncmp(s, "UPS9600", 7)) ) { /* Insert kludges for Fiskars UPS9000 here */ upslogx(LOG_INFO, "Fiskars UPS9000 detected, protocol kludges activated"); batt_volt_nom = 384; dstate_setinfo("battery.voltage.nominal", "%.0f", batt_volt_nom); } else { outpwr_factor *= 3; } change_name(simple, "output.current", "output.L1.current"); change_name(simple, "output.current.peak", "output.L1.current.peak"); change_name(simple, "output.realpower", "output.L1.realpower"); change_name(simple, "output.power", "output.L1.power"); change_name(simple, "output.voltage", "output.L1-N.voltage"); } dstate_setinfo("input.phases", "%d", num_inphases); dstate_setinfo("output.phases", "%d", num_outphases); inited_phaseinfo=1; } load = calc_upsload(); if (load >= 0) { upsdebugx(2, "ups.load: %.1f", load*100); dstate_setinfo("ups.load", "%.1f", load*100); } else { upsdebugx(2, "ups.load: No value"); } /* TODO/FIXME: Set UPS date/time on startup and daily if needed */ if (can_updt) { char dtbuf[UPSC_BUFLEN]; if (upsc_getvalue("UPDT", "0", "ACDT", NULL, dtbuf)) { dstate_setinfo("ups.date", "%s", dtbuf); } } if (can_uptm) { char tmbuf[UPSC_BUFLEN]; if (upsc_getvalue("UPTM", "0", "ACTM", NULL, tmbuf)) { dstate_setinfo("ups.time", "%s", tmbuf); } } if (batt_charge < 0) { if (batt_current < 0) { /* Reset battery current history if discharging */ numbatthist = lastbatthist = 0; } batt_charge = batt_charge_pct(); } if (batt_charge >= 0) { dstate_setinfo("battery.charge", "%.1f", batt_charge); } else { dstate_delinfo("battery.charge"); } /* 9999 == unknown value */ if (batt_runtime >= 0 && batt_runtime < 9999) { dstate_setinfo("battery.runtime", "%.0f", batt_runtime*60); } else if (load > 0 && batt_disch_curr_max != 0) { float est_battcurr = load * abs(batt_disch_curr_max); /* Peukert equation */ float runtime = (batt_cap_nom*3600)/pow(est_battcurr, 1.35); upsdebugx(2, "Calculated runtime: %.0f seconds", runtime); if (batt_runtime_max > 0 && runtime > batt_runtime_max*60) { runtime = batt_runtime_max*60; } dstate_setinfo("battery.runtime", "%.0f", runtime); } else if (batt_runtime_max > 0) { /* Show max possible runtime as reported by UPS */ dstate_setinfo("battery.runtime", "%.0f", batt_runtime_max*60); } else { dstate_delinfo("battery.runtime"); } /* Some UPSen only provides this when on battery, so reset between * each iteration to make sure we use the right value */ batt_charge = -1; batt_runtime = -1; if (!(status & UPSC_STAT_ONBATT)) status |= UPSC_STAT_ONLINE; upsc_setstatus(status); dstate_dataok(); ser_comm_good(); }
void upsdrv_initinfo(void) { char response[MAX_RESPONSE_LENGTH]; unsigned int min_low_transfer, max_low_transfer; unsigned int min_high_transfer, max_high_transfer; unsigned int i; char *ptr; if (!init_comm()) fatalx(EXIT_FAILURE, "Unable to detect Tripp Lite SmartOnline UPS on port %s\n", device_path); min_low_transfer = max_low_transfer = 0; min_high_transfer = max_high_transfer = 0; /* get all the read-only fields here */ if (do_command(POLL, MANUFACTURER, "", response) > 0) dstate_setinfo("ups.mfr", "%s", response); if (do_command(POLL, MODEL, "", response) > 0) dstate_setinfo("ups.model", "%s", response); if (do_command(POLL, VERSION_CMD, "", response) > 0) dstate_setinfo("ups.firmware", "%s", response); if (do_command(POLL, RATINGS, "", response) > 0) { ptr = field(response, 0); if (ptr) dstate_setinfo("input.voltage.nominal", "%d", atoi(ptr)); ptr = field(response, 2); if (ptr) { dstate_setinfo("output.voltage.nominal", "%d", atoi(ptr)); } ptr = field(response, 14); if (ptr) dstate_setinfo("battery.voltage.nominal", "%d", atoi(ptr)); ptr = field(response, 10); if (ptr) min_low_transfer = atoi(ptr); ptr = field(response, 9); if (ptr) max_low_transfer = atoi(ptr); ptr = field(response, 12); if (ptr) min_high_transfer = atoi(ptr); ptr = field(response, 11); if (ptr) max_high_transfer = atoi(ptr); } if (do_command(POLL, OUTLET_RELAYS, "", response) > 0) ups.outlet_banks = atoi(response); /* define things that are settable */ if (get_identification()) { dstate_setflags("ups.id", ST_FLAG_RW | ST_FLAG_STRING); dstate_setaux("ups.id", 100); } if (get_transfer_voltage_low() && max_low_transfer) { dstate_setflags("input.transfer.low", ST_FLAG_RW); for (i = min_low_transfer; i <= max_low_transfer; i++) dstate_addenum("input.transfer.low", "%d", i); } if (get_transfer_voltage_high() && max_low_transfer) { dstate_setflags("input.transfer.high", ST_FLAG_RW); for (i = min_high_transfer; i <= max_high_transfer; i++) dstate_addenum("input.transfer.high", "%d", i); } if (get_sensitivity()) { dstate_setflags("input.sensitivity", ST_FLAG_RW); for (i = 0; i < sizeof(sensitivity) / sizeof(sensitivity[0]); i++) dstate_addenum("input.sensitivity", "%s", sensitivity[i].name); } if (ups.outlet_banks) { dstate_addcmd("load.off"); dstate_addcmd("load.on"); } dstate_addcmd("shutdown.reboot"); dstate_addcmd("shutdown.reboot.graceful"); dstate_addcmd("shutdown.return"); #if 0 /* doesn't work */ dstate_addcmd("shutdown.stayoff"); #endif dstate_addcmd("shutdown.stop"); dstate_addcmd("test.battery.start"); dstate_addcmd("test.battery.stop"); /* add all the variables that change regularly */ upsdrv_updateinfo(); upsh.instcmd = instcmd; upsh.setvar = setvar; printf("Detected %s %s on %s\n", dstate_getinfo("ups.mfr"), dstate_getinfo("ups.model"), device_path); }
/* Process status bits */ int blazer_process_status_bits(item_t *item, char *value, const size_t valuelen) { char *val = ""; if (strspn(item->value, "01") != 1) { upsdebugx(3, "%s: unexpected value %s@%d->%s", __func__, item->value, item->from, item->value); return -1; } switch (item->from) { case 38: /* Utility Fail (Immediate) */ if (item->value[0] == '1') val = "!OL"; else val = "OL"; break; case 39: /* Battery Low */ if (item->value[0] == '1') val = "LB"; else val = "!LB"; break; case 40: /* Bypass/Boost or Buck Active */ if (item->value[0] == '1') { double vi, vo; vi = strtod(dstate_getinfo("input.voltage"), NULL); vo = strtod(dstate_getinfo("output.voltage"), NULL); if (vo < 0.5 * vi) { upsdebugx(2, "%s: output voltage too low", __func__); return -1; } else if (vo < 0.95 * vi) { val = "TRIM"; } else if (vo < 1.05 * vi) { val = "BYPASS"; } else if (vo < 1.5 * vi) { val = "BOOST"; } else { upsdebugx(2, "%s: output voltage too high", __func__); return -1; } } break; case 41: /* UPS Failed - ups.alarm */ if (item->value[0] == '1') val = "UPS selftest failed!"; break; case 42: /* UPS Type - ups.type */ if (item->value[0] == '1') val = "offline / line interactive"; else val = "online"; break; case 43: /* Test in Progress */ if (item->value[0] == '1') val = "CAL"; else val = "!CAL"; break; case 44: /* Shutdown Active */ if (item->value[0] == '1') val = "FSD"; else val = "!FSD"; break; case 45: /* Beeper status - ups.beeper.status */ if (item->value[0] == '1') val = "enabled"; else val = "disabled"; break; default: /* Don't know what happened */ return -1; } snprintf(value, valuelen, "%s", val); return 0; }
static float calc_upsload(void) { float load=-1, nom_out_power=-1, nom_out_realpower=-1, maxcurr, tmp; const char *s; /* Some UPSen (Fiskars 9000 for example) only reports current, and * only the max current */ if (nom_out_current > 0) { maxcurr = nom_out_current; } else { maxcurr = max_out_current; } if (maxcurr > 0) { if ((s=dstate_getinfo("output.L1.current")) || (s=dstate_getinfo("output.current"))) { if (sscanf(s, "%f", &tmp) == 1) { load = tmp/maxcurr; } } if ((s=dstate_getinfo("output.L2.current"))) { if (sscanf(s, "%f", &tmp) == 1) { tmp=tmp/maxcurr; if (tmp>load) { load = tmp; } } } if ((s=dstate_getinfo("output.L3.current"))) { if (sscanf(s, "%f", &tmp) == 1) { tmp=tmp/maxcurr; if (tmp>load) { load = tmp; } } } } /* This is aggregated (all phases) */ if ((s=dstate_getinfo("ups.power.nominal"))) { if (sscanf(s, "%f", &nom_out_power) != 1) { nom_out_power = -1; } } if (nom_out_power > 0) { if ((s=dstate_getinfo("output.L1.power"))) { if (sscanf(s, "%f", &tmp) == 1) { tmp /= (nom_out_power/num_outphases); if (tmp>load) { load = tmp; } dstate_setinfo("output.L1.power.percent", "%.1f", tmp*100); } } if ((s=dstate_getinfo("output.L2.power"))) { if (sscanf(s, "%f", &tmp) == 1) { tmp /= (nom_out_power/num_outphases); if (tmp>load) { load = tmp; } dstate_setinfo("output.L2.power.percent", "%.1f", tmp*100); } } if ((s=dstate_getinfo("output.L3.power"))) { if (sscanf(s, "%f", &tmp) == 1) { tmp /= (nom_out_power/num_outphases); if (tmp>load) { load = tmp; } dstate_setinfo("output.L3.power.percent", "%.1f", tmp*100); } } } /* This is aggregated (all phases) */ if ((s=dstate_getinfo("output.realpower.nominal"))) { if (sscanf(s, "%f", &nom_out_realpower) != 1) { nom_out_realpower = -1; } } if (nom_out_realpower >= 0) { if ((s=dstate_getinfo("output.L1.realpower"))) { if (sscanf(s, "%f", &tmp) == 1) { tmp /= (nom_out_realpower/num_outphases); if (tmp>load) { load = tmp; } dstate_setinfo("output.L1.realpower.percent", "%.1f", tmp*100); } } if ((s=dstate_getinfo("output.L2.realpower"))) { if (sscanf(s, "%f", &tmp) == 1) { tmp /= (nom_out_realpower/num_outphases); if (tmp>load) { load = tmp; } dstate_setinfo("output.L2.realpower.percent", "%.1f", tmp*100); } } if ((s=dstate_getinfo("output.L3.realpower"))) { if (sscanf(s, "%f", &tmp) == 1) { tmp /= (nom_out_realpower/num_outphases); if (tmp>load) { load = tmp; } dstate_setinfo("output.L3.realpower.percent", "%.1f", tmp*100); } } } return load; }
static void getbaseinfo(void) { unsigned char temp[256]; unsigned char Pacote[37]; int tam, i, j=0; time_t tmt; struct tm *now; const char *Model; time( &tmt ); now = localtime( &tmt ); dian = now->tm_mday; mesn = now->tm_mon+1; anon = now->tm_year+1900; weekn = now->tm_wday; /* trying detect rhino model */ while ( ( !detected ) && ( j < 10 ) ) { temp[0] = 0; /* flush temp buffer */ tam = ser_get_buf_len(upsfd, temp, pacsize, 3, 0); if( tam == 37 ) { for( i = 0 ; i < tam ; i++ ) { Pacote[i] = temp[i]; } } j++; if( tam == 37) CommReceive(Pacote, tam); else CommReceive(temp, tam); } if( (!detected) ) { fatalx(EXIT_FAILURE, NO_RHINO ); } switch( RhinoModel ) { case 0xC0: { Model = "Rhino 20.0 kVA"; PotenciaNominal = 20000; break; } case 0xC1: { Model = "Rhino 10.0 kVA"; PotenciaNominal = 10000; break; } case 0xC2: { Model = "Rhino 6.0 kVA"; PotenciaNominal = 6000; break; } case 0xC3: { Model = "Rhino 7.5 kVA"; PotenciaNominal = 7500; break; } default: { Model = "Rhino unknown model"; PotenciaNominal = 0; break; } } /* manufacturer and model */ dstate_setinfo("ups.mfr", "%s", "Microsol"); dstate_setinfo("ups.model", "%s", Model); /* dstate_setinfo("input.transfer.low", "%03.1f", InDownLim); LimInfBattInv ? dstate_setinfo("input.transfer.high", "%03.1f", InUpLim); LimSupBattInv ? */ dstate_addcmd("shutdown.stayoff"); /* CMD_SHUT */ /* there is no reserved words for CMD_INON and CMD_INOFF yet */ /* dstate_addcmd("input.on"); */ /* CMD_INON = 1 */ /* dstate_addcmd("input.off"); */ /* CMD_INOFF = 2 */ dstate_addcmd("load.on"); /* CMD_OUTON = 3 */ dstate_addcmd("load.off"); /* CMD_OUTOFF = 4 */ dstate_addcmd("bypass.start"); /* CMD_PASSON = 5 */ dstate_addcmd("bypass.stop"); /* CMD_PASSOFF = 6 */ printf("Detected %s on %s\n", dstate_getinfo("ups.model"), device_path); }
void upsdrv_initinfo(void) { int i,j, k; int VRange=0; int timevalue; int RetValue; char buffer[256], buffer2[32]; /* All families should reply to this request so we can confirm that it is * an ONEAC UPS */ ser_flush_in(upsfd,"",0); ser_send(upsfd,"%c%s",GET_FAMILY,COMMAND_END); if(OneacGetResponse (buffer, sizeof(buffer), 2)) { fatalx(EXIT_FAILURE, "Serial timeout with ONEAC UPS on %s\n", device_path); } else { if (strncmp(buffer,FAMILY_ON,FAMILY_SIZE) != 0 && strncmp(buffer,FAMILY_OZ,FAMILY_SIZE) != 0 && strncmp(buffer,FAMILY_OB,FAMILY_SIZE) != 0 && strncmp(buffer,FAMILY_EG,FAMILY_SIZE) != 0) { fatalx(EXIT_FAILURE, "Did not find an ONEAC UPS on %s\n", device_path); } } /* UPS Model (either EG, ON, OZ or OB series of UPS) */ strncpy(UpsFamily, buffer, FAMILY_SIZE); UpsFamily[2] = '\0'; dstate_setinfo("device.model", "%s",UpsFamily); printf("Found %s family of Oneac UPS\n", UpsFamily); dstate_setinfo("ups.type", "%s", "Line Interactive"); dstate_addcmd("test.battery.start.quick"); dstate_addcmd("test.battery.stop"); dstate_addcmd("test.failure.start"); dstate_addcmd("shutdown.return"); dstate_addcmd("shutdown.stop"); dstate_addcmd("shutdown.reboot"); upsh.setvar = setcmd; upsh.instcmd = instcmd; /* set some stuff that shouldn't change after initialization */ /* this stuff is common to all families of UPS */ ser_send(upsfd,"%c%s",GET_ALL,COMMAND_END); if (strncmp(UpsFamily, FAMILY_EG, FAMILY_SIZE) == 0) { RetValue = OneacGetResponse (buffer, sizeof(buffer), GETALL_EG_RESP_SIZE); } else { RetValue = OneacGetResponse (buffer, sizeof(buffer), GETALL_RESP_SIZE); } if(RetValue) { fatalx(EXIT_FAILURE, "Serial timeout(2) with ONEAC UPS on %s\n", device_path); } /* Manufacturer */ dstate_setinfo("device.mfr", "%.5s", buffer); /*firmware revision*/ dstate_setinfo("ups.firmware", "%.3s",buffer+7); /*nominal AC frequency setting --either 50 or 60*/ dstate_setinfo("input.frequency.nominal", "%.2s", buffer+20); dstate_setinfo("output.frequency.nominal", "%.2s", buffer+20); /* Shutdown delay in seconds...can be changed by user */ if (getval("offdelay") == NULL) dstate_setinfo("ups.delay.shutdown", "0"); else dstate_setinfo("ups.delay.shutdown", "%s", getval("offdelay")); dstate_setflags("ups.delay.shutdown", ST_FLAG_STRING | ST_FLAG_RW); dstate_setaux("ups.delay.shutdown", GET_SHUTDOWN_RESP_SIZE); /* Setup some ON/OZ/OB only stuff ... i.e. not EG */ if (strncmp(UpsFamily, FAMILY_EG, FAMILY_SIZE) != 0) { dstate_addcmd("reset.input.minmax"); /*nominal input voltage*/ VRange = buffer[26]; /* Keep for later use also */ switch (VRange) /* Will be '1' or '2' */ { case V120AC: dstate_setinfo("input.voltage.nominal", "120"); dstate_setinfo("output.voltage.nominal", "120"); break; case V230AC: dstate_setinfo("input.voltage.nominal", "230"); dstate_setinfo("output.voltage.nominal", "230"); break; default: upslogx(LOG_INFO,"Oneac: " "Invalid nom voltage parameter from UPS [%c]", VRange); } } /* Setup some OZ/OB only stuff */ if ((strncmp (UpsFamily, FAMILY_OZ, FAMILY_SIZE) == 0) || (strncmp (UpsFamily, FAMILY_OB, FAMILY_SIZE) == 0)) { dstate_addcmd("test.panel.start"); dstate_addcmd("test.battery.start.deep"); dstate_addcmd("beeper.enable"); dstate_addcmd("beeper.disable"); dstate_addcmd("beeper.mute"); dstate_setaux("ups.delay.shutdown", GETX_SHUTDOWN_RESP_SIZE); ser_flush_in(upsfd,"",0); ser_send(upsfd,"%c%s",GETX_ALL_2,COMMAND_END); if(OneacGetResponse (buffer, sizeof(buffer), GETX_ALL2_RESP_SIZE)) { fatalx(EXIT_FAILURE, "Serial timeout(3) with ONEAC UPS on %s\n", device_path); } /* Low and high output trip points */ EliminateLeadingZeroes (buffer+73, 3, buffer2, sizeof(buffer2)); dstate_setinfo("input.transfer.low", "%s", buffer2); dstate_setflags("input.transfer.low", ST_FLAG_STRING | ST_FLAG_RW ); dstate_setaux("input.transfer.low", 3); EliminateLeadingZeroes (buffer+76, 3, buffer2, sizeof(buffer2)); dstate_setinfo("input.transfer.high", "%s", buffer2); dstate_setflags("input.transfer.high", ST_FLAG_STRING | ST_FLAG_RW); dstate_setaux("input.transfer.high", 3); /* Restart delay */ EliminateLeadingZeroes (buffer+84, 4, buffer2, sizeof(buffer2)); dstate_setinfo("ups.delay.start", "%s", buffer2); dstate_setflags("ups.delay.start", ST_FLAG_STRING | ST_FLAG_RW); dstate_setaux("ups.delay.start", 4); /* Low Batt at time */ strncpy(buffer2, buffer+82, 2); buffer2[2]='\0'; timevalue = atoi(buffer2) * 60; /* Change minutes to seconds */ dstate_setinfo("battery.runtime.low", "%d",timevalue); dstate_setflags("battery.runtime.low", ST_FLAG_STRING | ST_FLAG_RW); dstate_setaux("battery.runtime.low", 2); /*Get the actual model string for ON UPS reported as OZ/OB family*/ /*UPS Model (full string)*/ memset(buffer2, '\0', 32); strncpy(buffer2, buffer+5, 10); for (i = 9; i >= 0 && buffer2[i] == ' '; --i) { buffer2[i] = '\0'; } dstate_setinfo("device.model", "%s", buffer2); /* Serial number */ dstate_setinfo("device.serial", "%.4s-%.4s", buffer+18, buffer+22); printf("Found %.10s UPS with serial number %.4s-%.4s\n", buffer2, buffer+18, buffer+22); /* Manufacture Date */ dstate_setinfo("ups.mfr.date", "%.6s (yymmdd)", buffer+38); /* Battery Replace Date */ dstate_setinfo("battery.date", "%.6s (yymmdd)", buffer+44); dstate_setflags("battery.date", ST_FLAG_STRING | ST_FLAG_RW); dstate_setaux("battery.date", 6); /* Real power nominal */ EliminateLeadingZeroes (buffer+55, 5, buffer2, sizeof(buffer2)); dstate_setinfo("ups.realpower.nominal", "%s", buffer2); /* Set up ups.start.auto to be writable */ dstate_setinfo("ups.start.auto", "yes"); dstate_setflags("ups.start.auto", ST_FLAG_STRING | ST_FLAG_RW); dstate_setaux("ups.start.auto", 3); /* Get output window min/max points from OB or OZ v1.9 or later */ if ((strncmp (UpsFamily, FAMILY_OB, FAMILY_SIZE) == 0) || (strcmp (dstate_getinfo("ups.firmware"), MIN_ALLOW_FW) >= 0 )) { upsdebugx (2,"Can get output window min/max! (%s)", dstate_getinfo("ups.firmware")); ser_send(upsfd,"%s%s",GETX_ALLOW_RANGE,COMMAND_END); if(OneacGetResponse (buffer, sizeof(buffer), GETX_RANGE_RESP_SIZE)) { fatalx(EXIT_FAILURE, "Serial timeout(4) with ONEAC UPS on %s\n",device_path); } strncpy(buffer2, buffer, 3); buffer2[3]='\0'; i = atoi(buffer2); /* Minimum voltage */ strncpy(buffer2, buffer+4, 3); j = atoi(buffer2); /* Maximum voltage */ strncpy(buffer2, buffer+8, 2); buffer2[2]='\0'; k = atoi(buffer2); /* Spread between */ dstate_setinfo("input.transfer.low.min", "%3d", i); dstate_setinfo("input.transfer.low.max", "%3d", j-k); dstate_setinfo("input.transfer.high.min", "%3d", i+k); dstate_setinfo("input.transfer.high.max", "%3d", j); } else { /* Use default values from firmware */ upsdebugx (2,"Using trip defaults (%s)...", dstate_getinfo("ups.firmware")); switch (VRange) /* Held from initial use */ { case V120AC: dstate_setinfo("input.transfer.low.min", "90"); dstate_setinfo("input.transfer.low.max", "120"); dstate_setinfo("input.transfer.high.min", "110"); dstate_setinfo("input.transfer.high.max", "140"); break; case V230AC: dstate_setinfo("input.transfer.low.min", "172"); dstate_setinfo("input.transfer.low.max", "228"); dstate_setinfo("input.transfer.high.min", "212"); dstate_setinfo("input.transfer.high.max", "268"); break; default: ; } } } }
static int netxml_alarm_subscribe(const char *page) { int ret, port = -1, secret = -1; char buf[LARGEBUF], *s; ne_request *request; ne_sock_addr *addr; const ne_inet_addr *ai; char resp_buf[LARGEBUF]; /* Clear response buffer */ memset(resp_buf, 0, sizeof(resp_buf)); upsdebugx(2, "%s: %s", __func__, page); sock = ne_sock_create(); if (gethostname(buf, sizeof(buf)) == 0) { dstate_setinfo("driver.hostname", "%s", buf); } else { dstate_setinfo("driver.hostname", "<unknown>"); } #ifdef HAVE_NE_SOCK_CONNECT_TIMEOUT ne_sock_connect_timeout(sock, timeout); #endif ne_sock_read_timeout(sock, 1); netxml_get_page(subdriver->configure); snprintf(buf, sizeof(buf), "<?xml version=\"1.0\"?>\n"); snprintfcat(buf, sizeof(buf), "<Subscribe>\n"); snprintfcat(buf, sizeof(buf), "<Class>%s v%s</Class>\n", progname, DRIVER_VERSION); snprintfcat(buf, sizeof(buf), "<Type>connected socket</Type>\n"); snprintfcat(buf, sizeof(buf), "<HostName>%s</HostName>\n", dstate_getinfo("driver.hostname")); snprintfcat(buf, sizeof(buf), "<XMLClientParameters>\n"); snprintfcat(buf, sizeof(buf), "<ShutdownDuration>%d</ShutdownDuration>\n", shutdown_duration); if( shutdown_timer > 0 ) { snprintfcat(buf, sizeof(buf), "<ShutdownTimer>%d</ShutdownTimer>\r\n", shutdown_timer); } else { snprintfcat(buf, sizeof(buf), "<ShutdownTimer>NONE</ShutdownTimer>\n"); } snprintfcat(buf, sizeof(buf), "<AutoConfig>LOCAL</AutoConfig>\n"); snprintfcat(buf, sizeof(buf), "<OutletGroup>1</OutletGroup>\n"); snprintfcat(buf, sizeof(buf), "</XMLClientParameters>\n"); snprintfcat(buf, sizeof(buf), "<Warning></Warning>\n"); snprintfcat(buf, sizeof(buf), "</Subscribe>\n"); /* now send subscription message setting all the proper flags */ request = ne_request_create(session, "POST", page); ne_set_request_body_buffer(request, buf, strlen(buf)); /* as the NMC reply is not xml standard compliant let's parse it this way */ do { #ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT alarm(timeout+1); #endif ret = ne_begin_request(request); #ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT alarm(0); #endif if (ret != NE_OK) { break; } ret = ne_read_response_block(request, resp_buf, sizeof(resp_buf)); if (ret == NE_OK) { ret = ne_end_request(request); } } while (ret == NE_RETRY); ne_request_destroy(request); /* due to different formats used by the various NMCs, we need to\ break up the reply in lines and parse each one separately */ for (s = strtok(resp_buf, "\r\n"); s != NULL; s = strtok(NULL, "\r\n")) { upsdebugx(2, "%s: parsing %s", __func__, s); if (!strncasecmp(s, "<Port>", 6) && (sscanf(s+6, "%u", &port) != 1)) { return NE_RETRY; } if (!strncasecmp(s, "<Secret>", 8) && (sscanf(s+8, "%u", &secret) != 1)) { return NE_RETRY; } } if ((port == -1) || (secret == -1)) { upsdebugx(2, "%s: parsing initial subcription failed", __func__); return NE_RETRY; } /* Resolve the given hostname. 'flags' must be zero. Hex * string IPv6 addresses (e.g. `::1') may be enclosed in brackets * (e.g. `[::1]'). */ addr = ne_addr_resolve(uri.host, 0); /* Returns zero if name resolution was successful, non-zero on * error. */ if (ne_addr_result(addr) != 0) { upsdebugx(2, "%s: name resolution failure on %s: %s", __func__, uri.host, ne_addr_error(addr, buf, sizeof(buf))); ne_addr_destroy(addr); return NE_RETRY; } for (ai = ne_addr_first(addr); ai != NULL; ai = ne_addr_next(addr)) { upsdebugx(2, "%s: connecting to host %s port %d", __func__, ne_iaddr_print(ai, buf, sizeof(buf)), port); #ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT alarm(timeout+1); #endif ret = ne_sock_connect(sock, ai, port); #ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT alarm(0); #endif if (ret == NE_OK) { upsdebugx(2, "%s: connection to %s open on fd %d", __func__, uri.host, ne_sock_fd(sock)); break; } } ne_addr_destroy(addr); if (ai == NULL) { upsdebugx(2, "%s: failed to create listening socket", __func__); return NE_RETRY; } snprintf(buf, sizeof(buf), "<Subscription Identification=\"%u\"></Subscription>", secret); ret = ne_sock_fullwrite(sock, buf, strlen(buf) + 1); if (ret != NE_OK) { upsdebugx(2, "%s: send failed: %s", __func__, ne_sock_error(sock)); return NE_RETRY; } ret = ne_sock_read(sock, buf, sizeof(buf)); if (ret < 1) { upsdebugx(2, "%s: read failed: %s", __func__, ne_sock_error(sock)); return NE_RETRY; } if (strcasecmp(buf, "<Subscription Answer=\"ok\"></Subscription>")) { upsdebugx(2, "%s: subscription rejected", __func__); return NE_RETRY; } upslogx(LOG_INFO, "NSM connection to '%s' established", uri.host); return NE_OK; }
int instcmd(const char *cmdname, const char *extra) { int i; upsdebugx(2, "In instcmd with %s and extra %s.", cmdname, extra); if (!strcasecmp(cmdname, "test.failure.start")) { ser_send(upsfd,"%s%s",SIM_PWR_FAIL,COMMAND_END); return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "shutdown.return")) { i = atoi(dstate_getinfo("ups.delay.shutdown")); if ((strncmp (UpsFamily, FAMILY_OZ, FAMILY_SIZE) == 0) || (strncmp (UpsFamily, FAMILY_OB, FAMILY_SIZE) == 0)) { upsdebugx(3, "Shutdown using %c%d...", DELAYED_SHUTDOWN_PREFIX, i); ser_send(upsfd,"%c%d%s",DELAYED_SHUTDOWN_PREFIX, i, COMMAND_END); } else { upsdebugx(3, "Shutdown using %c%03d...",DELAYED_SHUTDOWN_PREFIX, i); ser_send(upsfd,"%c%03d%s",DELAYED_SHUTDOWN_PREFIX, i, COMMAND_END); } return STAT_INSTCMD_HANDLED; } if(!strcasecmp(cmdname, "shutdown.reboot")) { ser_send(upsfd, "%s", SHUTDOWN); return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "shutdown.stop")) { ser_send(upsfd,"%c%s",DELAYED_SHUTDOWN_PREFIX,COMMAND_END); return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "test.battery.start.quick")) { do_battery_test(); return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "test.battery.start.deep")) { ser_send(upsfd, "%s%s", TEST_BATT_DEEP, COMMAND_END); return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "test.battery.stop")) { if ((strncmp (UpsFamily, FAMILY_EG, FAMILY_SIZE) == 0) || (strncmp (UpsFamily, FAMILY_ON, FAMILY_SIZE) == 0)) { ser_send(upsfd,"%s00%s",BAT_TEST_PREFIX,COMMAND_END); } else { ser_send(upsfd,"%c%s",TEST_ABORT,COMMAND_END); } return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "reset.input.minmax")) { ser_send(upsfd,"%c%s",RESET_MIN_MAX, COMMAND_END); return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "beeper.enable")) { ser_send(upsfd,"%c%c%s",SETX_BUZZER_PREFIX, BUZZER_ENABLED,COMMAND_END); return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "beeper.disable")) { ser_send(upsfd,"%c%c%s",SETX_BUZZER_PREFIX,BUZZER_DISABLED,COMMAND_END); return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "beeper.mute")) { ser_send(upsfd,"%c%c%s",SETX_BUZZER_PREFIX, BUZZER_MUTED, COMMAND_END); return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "test.panel.start")) { ser_send(upsfd,"%s%s",TEST_INDICATORS, COMMAND_END); return STAT_INSTCMD_HANDLED; } upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname); return STAT_INSTCMD_UNKNOWN; }
int setcmd(const char* varname, const char* setvalue) { upsdebugx(2, "In setcmd for %s with %s...", varname, setvalue); if (!strcasecmp(varname, "ups.delay.shutdown")) { if ((strncmp (UpsFamily, FAMILY_OZ, FAMILY_SIZE) == 0) || (strncmp (UpsFamily, FAMILY_OB, FAMILY_SIZE) == 0)) { if (atoi(setvalue) > 65535) { upsdebugx(2, "Too big for OZ/OB (>65535)...(%s)", setvalue); return STAT_SET_UNKNOWN; } } else { if (atoi(setvalue) > 999) { upsdebugx(2, "Too big for EG/ON (>999)...(%s)", setvalue); return STAT_SET_UNKNOWN; } } dstate_setinfo("ups.delay.shutdown", "%s", setvalue); return STAT_SET_HANDLED; } if (!strcasecmp(varname, "input.transfer.low")) { if (SetOutputAllow(setvalue, dstate_getinfo("input.transfer.high"))) { return STAT_SET_UNKNOWN; } else { dstate_setinfo("input.transfer.low" , "%s", setvalue); return STAT_SET_HANDLED; } } if (!strcasecmp(varname, "input.transfer.high")) { if (SetOutputAllow(dstate_getinfo("input.transfer.low"), setvalue)) { return STAT_SET_UNKNOWN; } else { dstate_setinfo("input.transfer.high" , "%s", setvalue); return STAT_SET_HANDLED; } } if (!strcasecmp(varname, "battery.date")) { if(strlen(setvalue) == GETX_DATE_RESP_SIZE) /* yymmdd (6 chars) */ { ser_send(upsfd, "%s%s%s", SETX_BATTERY_DATE, setvalue, COMMAND_END); dstate_setinfo("battery.date", "%s (yymmdd)", setvalue); return STAT_SET_HANDLED; } else { return STAT_SET_UNKNOWN; } } if (!strcasecmp(varname, "ups.delay.start")) { if (atoi(setvalue) <= 9999) { ser_send(upsfd,"%s%s%s",SETX_RESTART_DELAY, setvalue, COMMAND_END); dstate_setinfo("ups.delay.start", "%s", setvalue); return STAT_SET_HANDLED; } else { return STAT_SET_UNKNOWN; } } if (!strcasecmp(varname, "battery.runtime.low")) { if (atoi(setvalue) <= 99) { ser_send(upsfd,"%s%s%s",SETX_LOWBATT_AT, setvalue, COMMAND_END); dstate_setinfo("battery.runtime.low", "%s", setvalue); return STAT_SET_HANDLED; } else { return STAT_SET_UNKNOWN; } } if (!strcasecmp(varname, "ups.start.auto")) { if (!strcasecmp(setvalue, "yes")) { ser_send(upsfd,"%c0%s",SETX_AUTO_START, COMMAND_END); dstate_setinfo("ups.start.auto", "yes"); return STAT_SET_HANDLED; } else if (!strcasecmp(setvalue, "no")) { ser_send(upsfd,"%c1%s",SETX_AUTO_START, COMMAND_END); dstate_setinfo("ups.start.auto", "no"); return STAT_SET_HANDLED; } return STAT_SET_UNKNOWN; } upslogx(LOG_NOTICE, "setcmd: unknown command [%s]", varname); return STAT_SET_UNKNOWN; }
int riello_instcmd(const char *cmdname, const char *extra) { uint8_t length; uint16_t delay; const char *delay_char; if (!riello_test_bit(&DevData.StatusCode[0], 1)) { if (!strcasecmp(cmdname, "load.off")) { delay = 0; riello_init_serial(); if (typeRielloProtocol == DEV_RIELLOGPSER) length = riello_prepare_cs(bufOut, gpser_error_control, delay); else length = riello_prepare_shutsentr(bufOut, delay); if (ser_send_buf(upsfd, bufOut, length) == 0) { upsdebugx (3, "Command load.off communication error"); return STAT_INSTCMD_FAILED; } riello_serialcomm(&bufIn[0], typeRielloProtocol); if (!wait_packet && foundbadcrc) { upsdebugx (3, "Command load.off Ko: bad CRC or Checksum"); return STAT_INSTCMD_FAILED; } if (!wait_packet && foundnak) { upsdebugx (3, "Command load.off Ko: command not supported"); return STAT_INSTCMD_FAILED; } upsdebugx (3, "Command load.off Ok"); return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "load.off.delay")) { delay_char = dstate_getinfo("ups.delay.shutdown"); delay = atoi(delay_char); riello_init_serial(); if (typeRielloProtocol == DEV_RIELLOGPSER) length = riello_prepare_cs(bufOut, gpser_error_control, delay); else length = riello_prepare_shutsentr(bufOut, delay); if (ser_send_buf(upsfd, bufOut, length) == 0) { upsdebugx (3, "Command load.off delay communication error"); return STAT_INSTCMD_FAILED; } riello_serialcomm(&bufIn[0], typeRielloProtocol); if (!wait_packet && foundbadcrc) { upsdebugx (3, "Command load.off.delay Ko: bad CRC or Checksum"); return STAT_INSTCMD_FAILED; } if (!wait_packet && foundnak) { upsdebugx (3, "Command load.off.delay Ko: command not supported"); return STAT_INSTCMD_FAILED; } upsdebugx (3, "Command load.off delay Ok"); return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "load.on")) { delay = 0; riello_init_serial(); if (typeRielloProtocol == DEV_RIELLOGPSER) length = riello_prepare_cr(bufOut, gpser_error_control, delay); else { length = riello_prepare_setrebsentr(bufOut, delay); if (ser_send_buf(upsfd, bufOut, length) == 0) { upsdebugx (3, "Command load.on communication error"); return STAT_INSTCMD_FAILED; } riello_serialcomm(&bufIn[0], typeRielloProtocol); if (!wait_packet && foundbadcrc) { upsdebugx (3, "Command load.on Ko: bad CRC or Checksum"); return STAT_INSTCMD_FAILED; } if (!wait_packet && foundnak) { upsdebugx (3, "Command load.on Ko: command not supported"); return STAT_INSTCMD_FAILED; } length = riello_prepare_rebsentr(bufOut, delay); } if (ser_send_buf(upsfd, bufOut, length) == 0) { upsdebugx (3, "Command load.on communication error"); return STAT_INSTCMD_FAILED; } riello_serialcomm(&bufIn[0], typeRielloProtocol); if (!wait_packet && foundbadcrc) { upsdebugx (3, "Command load.on Ko: bad CRC or Checksum"); return STAT_INSTCMD_FAILED; } if (!wait_packet && foundnak) { upsdebugx (3, "Command load.on Ko: command not supported"); return STAT_INSTCMD_FAILED; } upsdebugx (3, "Command load.on Ok"); return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "load.on.delay")) { delay_char = dstate_getinfo("ups.delay.reboot"); delay = atoi(delay_char); riello_init_serial(); if (typeRielloProtocol == DEV_RIELLOGPSER) length = riello_prepare_cr(bufOut, gpser_error_control, delay); else { length = riello_prepare_setrebsentr(bufOut, delay); if (ser_send_buf(upsfd, bufOut, length) == 0) { upsdebugx (3, "Command load.on delay communication error"); return STAT_INSTCMD_FAILED; } riello_serialcomm(&bufIn[0], typeRielloProtocol); if (!wait_packet && foundbadcrc) { upsdebugx (3, "Command load.on delay Ko: bad CRC or Checksum"); return STAT_INSTCMD_FAILED; } if (!wait_packet && foundnak) { upsdebugx (3, "Command load.on delay Ko: command not supported"); return STAT_INSTCMD_FAILED; } length = riello_prepare_rebsentr(bufOut, delay); } if (ser_send_buf(upsfd, bufOut, length) == 0) { upsdebugx (3, "Command load.on delay communication error"); return STAT_INSTCMD_FAILED; } riello_serialcomm(&bufIn[0], typeRielloProtocol); if (!wait_packet && foundbadcrc) { upsdebugx (3, "Command load.on.delay Ko: bad CRC or Checksum"); return STAT_INSTCMD_FAILED; } if (!wait_packet && foundnak) { upsdebugx (3, "Command load.on.delay Ko: command not supported"); return STAT_INSTCMD_FAILED; } upsdebugx (3, "Command load.on delay Ok"); return STAT_INSTCMD_HANDLED; } } else { if (!strcasecmp(cmdname, "shutdown.return")) { delay_char = dstate_getinfo("ups.delay.shutdown"); delay = atoi(delay_char); riello_init_serial(); if (typeRielloProtocol == DEV_RIELLOGPSER) length = riello_prepare_cs(bufOut, gpser_error_control, delay); else length = riello_prepare_shutsentr(bufOut, delay); if (ser_send_buf(upsfd, bufOut, length) == 0) { upsdebugx (3, "Command shutdown.return communication error"); return STAT_INSTCMD_FAILED; } riello_serialcomm(&bufIn[0], typeRielloProtocol); if (!wait_packet && foundbadcrc) { upsdebugx (3, "Command shutdown.return Ko: bad CRC or Checksum"); return STAT_INSTCMD_FAILED; } if (!wait_packet && foundnak) { upsdebugx (3, "Command shutdown.return Ko: command not supported"); return STAT_INSTCMD_FAILED; } upsdebugx (3, "Command shutdown.return Ok"); return STAT_INSTCMD_HANDLED; } } if (!strcasecmp(cmdname, "shutdown.stop")) { riello_init_serial(); if (typeRielloProtocol == DEV_RIELLOGPSER) length = riello_prepare_cd(bufOut, gpser_error_control); else length = riello_prepare_cancelsentr(bufOut); if (ser_send_buf(upsfd, bufOut, length) == 0) { upsdebugx (3, "Command shutdown.stop communication error"); return STAT_INSTCMD_FAILED; } riello_serialcomm(&bufIn[0], typeRielloProtocol); if (!wait_packet && foundbadcrc) { upsdebugx (3, "Command shutdown.stop Ko: bad CRC or Checksum"); return STAT_INSTCMD_FAILED; } if (!wait_packet && foundnak) { upsdebugx (3, "Command shutdown.stop Ko: command not supported"); return STAT_INSTCMD_FAILED; } upsdebugx (3, "Command shutdown.stop Ok"); return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "test.panel.start")) { riello_init_serial(); length = riello_prepare_tp(bufOut, gpser_error_control); if (ser_send_buf(upsfd, bufOut, length) == 0) { upsdebugx (3, "Command test.panel.start communication error"); return STAT_INSTCMD_FAILED; } riello_serialcomm(&bufIn[0], DEV_RIELLOGPSER); if (!wait_packet && foundbadcrc) { upsdebugx (3, "Command test.panel.start Ko: bad CRC or Checksum"); return STAT_INSTCMD_FAILED; } if (!wait_packet && foundnak) { upsdebugx (3, "Command test.panel.start Ko: command not supported"); return STAT_INSTCMD_FAILED; } upsdebugx (3, "Command test.panel.start Ok"); return STAT_INSTCMD_HANDLED; } if (!strcasecmp(cmdname, "test.battery.start")) { riello_init_serial(); if (typeRielloProtocol == DEV_RIELLOGPSER) length = riello_prepare_tb(bufOut, gpser_error_control); else length = riello_prepare_tbsentr(bufOut); if (ser_send_buf(upsfd, bufOut, length) == 0) { upsdebugx (3, "Command test.battery.start communication error"); return STAT_INSTCMD_FAILED; } riello_serialcomm(&bufIn[0], typeRielloProtocol); if (!wait_packet && foundbadcrc) { upsdebugx (3, "Command battery.start Ko: bad CRC or Checksum"); return STAT_INSTCMD_FAILED; } if (!wait_packet && foundnak) { upsdebugx (3, "Command battery.start Ko: command not supported"); return STAT_INSTCMD_FAILED; } upsdebugx (3, "Command test.battery.start Ok"); return STAT_INSTCMD_HANDLED; } upslogx(LOG_NOTICE, "instcmd: unknown command [%s]", cmdname); return STAT_INSTCMD_UNKNOWN; }
/* update information */ void upsdrv_updateinfo(void) { char val[32]; if (!ups_getinfo()){ return; } /* input.frequency */ upsdebugx(3, "input.frequency (raw data): [raw: %u]", raw_data[INPUT_FREQUENCY]); dstate_setinfo("input.frequency", "%02.2f", input_freq()); upsdebugx(2, "input.frequency: %s", dstate_getinfo("input.frequency")); /* output.frequency */ upsdebugx(3, "output.frequency (raw data): [raw: %u]", raw_data[OUTPUT_FREQUENCY]); dstate_setinfo("output.frequency", "%02.2f", output_freq()); upsdebugx(2, "output.frequency: %s", dstate_getinfo("output.frequency")); /* ups.load */ upsdebugx(3, "ups.load (raw data): [raw: %u]", raw_data[UPS_LOAD]); dstate_setinfo("ups.load", "%03.1f", load_level()); upsdebugx(2, "ups.load: %s", dstate_getinfo("ups.load")); /* battery.charge */ upsdebugx(3, "battery.charge (raw data): [raw: %u]", raw_data[BATTERY_CHARGE]); dstate_setinfo("battery.charge", "%03.1f", batt_level()); upsdebugx(2, "battery.charge: %s", dstate_getinfo("battery.charge")); /* input.voltage */ upsdebugx(3, "input.voltage (raw data): [raw: %u]", raw_data[INPUT_VOLTAGE]); dstate_setinfo("input.voltage", "%03.1f",input_voltage()); upsdebugx(2, "input.voltage: %s", dstate_getinfo("input.voltage")); /* output.voltage */ upsdebugx(3, "output.voltage (raw data): [raw: %u]", raw_data[OUTPUT_VOLTAGE]); dstate_setinfo("output.voltage", "%03.1f",output_voltage()); upsdebugx(2, "output.voltage: %s", dstate_getinfo("output.voltage")); status_init(); *val = 0; if (!(raw_data[STATUS_A] & MAINS_FAILURE)) { !(raw_data[STATUS_A] & OFF) ? status_set("OL") : status_set("OFF"); } else { status_set("OB"); } if (raw_data[STATUS_A] & LOW_BAT) status_set("LB"); if (raw_data[STATUS_A] & AVR_ON) { input_voltage() < linevoltage ? status_set("BOOST") : status_set("TRIM"); } if (raw_data[STATUS_A] & OVERLOAD) status_set("OVER"); if (raw_data[STATUS_B] & BAD_BAT) status_set("RB"); if (raw_data[STATUS_B] & TEST) status_set("TEST"); status_commit(); upsdebugx(2, "STATUS: %s", dstate_getinfo("ups.status")); dstate_dataok(); }