/* * Generate status string from bitfield */ static void upsc_setstatus(unsigned int status) { /* * I'll look for all available statuses, even though they might not be * supported in the UPScode II protocol. */ status_init(); if (status & UPSC_STAT_ONLINE) status_set("OL"); if (status & UPSC_STAT_ONBATT) status_set("OB"); if (status & UPSC_STAT_LOBATT) status_set("LB"); if (status & UPSC_STAT_REPLACEBATT) status_set("RB"); if (status & UPSC_STAT_BOOST) status_set("BOOST"); if (status & UPSC_STAT_TRIM) status_set("TRIM"); if (status & UPSC_STAT_OVERLOAD) status_set("OVER"); if (status & UPSC_STAT_CALIBRATION) status_set("CAL"); if (status & UPSC_STAT_OFF) status_set("OFF"); if (status & UPSC_STAT_BYPASS) status_set("BYPASS"); status_commit(); }
void upsdrv_updateinfo(void) { if (ivt_status() < 7) { dstate_datastale(); return; } dstate_setinfo("battery.voltage", "%.2f", battery.voltage.act); dstate_setinfo("battery.voltage.minimum", "%.2f", battery.voltage.min); dstate_setinfo("battery.voltage.maximum", "%.2f", battery.voltage.max); dstate_setinfo("battery.current", "%.1f", battery.current.act); dstate_setinfo("battery.current.minimum", "%.1f", battery.current.min); dstate_setinfo("battery.current.maximum", "%.1f", battery.current.max); dstate_setinfo("battery.temperature", "%.0f", battery.temperature); status_init(); if (battery.current.act > 0) { status_set("OL"); /* charging */ } else { status_set("OB"); /* discharging */ } if (battery.voltage.act < battery.voltage.low) { status_set("LB"); } status_commit(); dstate_dataok(); }
static int setvar(const char *varname, const char *val) { dummy_info_t *item; upsdebugx(2, "entering setvar(%s, %s)", varname, val); /* FIXME: the below is only valid if (mode == MODE_DUMMY) * if (mode == MODE_REPEATER) => forward * if (mode == MODE_META) => ? */ if (!strncmp(varname, "ups.status", 10)) { status_init(); /* FIXME: split and check values (support multiple values), à la usbhid-ups */ status_set(val); status_commit(); return STAT_SET_HANDLED; } /* Check variable validity */ if (!is_valid_data(varname)) { upsdebugx(2, "setvar: invalid variable name (%s)", varname); return STAT_SET_UNKNOWN; } /* Check value validity */ if (!is_valid_value(varname, val)) { upsdebugx(2, "setvar: invalid value (%s) for variable (%s)", val, varname); return STAT_SET_UNKNOWN; } /* If value is empty, remove the variable (FIXME: do we need * a magic word?) */ if (strlen(val) == 0) { dstate_delinfo(varname); } else { dstate_setinfo(varname, "%s", val); if ( (item = find_info(varname)) != NULL) { dstate_setflags(item->info_type, item->info_flags); /* Set max length for strings, if needed */ if (item->info_flags & ST_FLAG_STRING) dstate_setaux(item->info_type, item->info_len); } } return STAT_SET_HANDLED; }
void upsdrv_updateinfo(void) { char reply[REPLY_PACKETSIZE]; int ret, online, battery_normal; if (!udev) { ret = usb_device_open(&udev, &usbdevice, &device_matcher, &driver_callback); if (ret < 0) { return; } } ret = query_ups(reply); if (ret < 4) { usb_comm_fail("Query to UPS failed"); dstate_datastale(); usb_device_close(udev); udev = NULL; return; } usb_comm_good(); dstate_dataok(); /* * 3rd bit of 4th byte indicates whether the UPS is on line (1) * or on battery (0) */ online = (reply[3]&4)>>2; /* * 2nd bit of 4th byte indicates battery status; normal (1) * or low (0) */ battery_normal = (reply[3]&2)>>1; status_init(); if (online) { status_set("OL"); } else { status_set("OB"); } if (!battery_normal) { status_set("LB"); } status_commit(); }
void upsdrv_updateinfo(void) { int r; int x,i=0,j,k,value; float value1; char ch; char data[10]; int data_position = 4; test_EOL(); x= ser_get_buf_len(upsfd,buf, 64, SER_WAIT_SEC,SER_WAIT_USEC); printf("reading status is %d\n",x); printf("the reading data is %s\n",buf); ser_comm_good(); r = test_CMD(); if(r != TRUE){ printf("command error\n"); return; } i = data_position; for(j =0;j< _countof(pacefield);j++) { for(k=0;k<pacefield[j].len;k++) { data[k] = buf[i+k]; } data[k] = '\0'; printf("the reading data is %s\n",data); value = atoi(data); value1 = (float)value/pacefield[j].divident; printf("value 1 = %f\n",value1); dstate_setinfo(pacefield[j].name, "%0.2f",value1); i = i+pacefield[j].len; } status_init(); update_err_status(); update_charge_source_status(); update_inverter_status(); update_battery_status(); update_load_status(); update_battery_charge_dchrg_status(); status_commit(); dstate_dataok(); }
void update_pseudovars( void ) { status_init(); if(strcmp(sec_varlist[9].value,"1")== 0) { status_set("OFF"); } if(strcmp(sec_varlist[76].value,"0")== 0) { status_set("OL"); } if(strcmp(sec_varlist[76].value,"1")== 0) { status_set("OB"); } if(strcmp(sec_varlist[76].value,"2")== 0) { status_set("BYPASS"); } if(strcmp(sec_varlist[76].value,"3")== 0) { status_set("TRIM"); } if(strcmp(sec_varlist[76].value,"4")== 0) { status_set("BOOST"); } if(strcmp(sec_varlist[10].value,"1")== 0) { status_set("OVER"); } if(strcmp(sec_varlist[22].value,"1")== 0) { status_set("LB"); } if(strcmp(sec_varlist[19].value,"2")== 0) { status_set("RB"); } status_commit(); }
void upsdrv_updateinfo(void) { getupdateinfo(); /* new package for updates */ dstate_setinfo("output.voltage", "%03.1f", OutVoltage); dstate_setinfo("input.voltage", "%03.1f", InVoltage); dstate_setinfo("battery.voltage", "%02.1f", BattVoltage); /* output and bypass tests */ if( OutputOn ) dstate_setinfo("outlet.switchable", "%s", "yes"); else dstate_setinfo("outlet.switchable", "%s", "no"); if( BypassOn ) dstate_setinfo("outlet.1.switchable", "%s", "yes"); else dstate_setinfo("outlet.1.switchable", "%s", "no"); status_init(); if (!SourceFail ) status_set("OL"); /* on line */ else status_set("OB"); /* on battery */ if (Autonomy < 5 ) status_set("LB"); /* low battery */ status_commit(); dstate_setinfo("ups.temperature", "%2.2f", Temperature); dstate_setinfo("input.frequency", "%2.1f", InFreq); dstate_dataok(); }
void upsdrv_updateinfo(void) { uint8_t getextendedOK; static int countlost = 0; int stat; upsdebugx(1, "countlost %d",countlost); if (countlost > 0){ upsdebugx(1, "Communication with UPS is lost: status read failed!"); if (countlost == COUNTLOST) { dstate_datastale(); upslogx(LOG_WARNING, "Communication with UPS is lost: status read failed!"); } } if (typeRielloProtocol == DEV_RIELLOGPSER) stat = get_ups_status(); else stat = get_ups_sentr(); if (stat < 0) { if (countlost < COUNTLOST) countlost++; return; } if (typeRielloProtocol == DEV_RIELLOGPSER) { if (get_ups_extended() == 0) getextendedOK = 1; else getextendedOK = 0; } else getextendedOK = 1; if (countlost == COUNTLOST) upslogx(LOG_NOTICE, "Communication with UPS is re-established!"); dstate_setinfo("input.frequency", "%.2f", DevData.Finp/10.0); dstate_setinfo("input.bypass.frequency", "%.2f", DevData.Fbypass/10.0); dstate_setinfo("output.frequency", "%.2f", DevData.Fout/10.0); dstate_setinfo("battery.voltage", "%.1f", DevData.Ubat/10.0); dstate_setinfo("battery.charge", "%u", DevData.BatCap); dstate_setinfo("battery.runtime", "%u", DevData.BatTime*60); dstate_setinfo("ups.temperature", "%u", DevData.Tsystem); if (input_monophase) { dstate_setinfo("input.voltage", "%u", DevData.Uinp1); dstate_setinfo("input.bypass.voltage", "%u", DevData.Ubypass1); } else { dstate_setinfo("input.L1-N.voltage", "%u", DevData.Uinp1); dstate_setinfo("input.L2-N.voltage", "%u", DevData.Uinp2); dstate_setinfo("input.L3-N.voltage", "%u", DevData.Uinp3); dstate_setinfo("input.bypass.L1-N.voltage", "%u", DevData.Ubypass1); dstate_setinfo("input.bypass.L2-N.voltage", "%u", DevData.Ubypass2); dstate_setinfo("input.bypass.L3-N.voltage", "%u", DevData.Ubypass3); } if (output_monophase) { dstate_setinfo("output.voltage", "%u", DevData.Uout1); dstate_setinfo("output.power.percent", "%u", DevData.Pout1); dstate_setinfo("ups.load", "%u", DevData.Pout1); } else { dstate_setinfo("output.L1-N.voltage", "%u", DevData.Uout1); dstate_setinfo("output.L2-N.voltage", "%u", DevData.Uout2); dstate_setinfo("output.L3-N.voltage", "%u", DevData.Uout3); dstate_setinfo("output.L1.power.percent", "%u", DevData.Pout1); dstate_setinfo("output.L2.power.percent", "%u", DevData.Pout2); dstate_setinfo("output.L3.power.percent", "%u", DevData.Pout3); dstate_setinfo("ups.load", "%u", (DevData.Pout1+DevData.Pout2+DevData.Pout3)/3); } status_init(); /* AC Fail */ if (riello_test_bit(&DevData.StatusCode[0], 1)) status_set("OB"); else status_set("OL"); /* LowBatt */ if ((riello_test_bit(&DevData.StatusCode[0], 1)) && (riello_test_bit(&DevData.StatusCode[0], 0))) status_set("LB"); /* Standby */ if (!riello_test_bit(&DevData.StatusCode[0], 3)) status_set("OFF"); /* On Bypass */ if (riello_test_bit(&DevData.StatusCode[1], 3)) status_set("BYPASS"); /* Overload */ if (riello_test_bit(&DevData.StatusCode[4], 2)) status_set("OVER"); /* Buck */ if (riello_test_bit(&DevData.StatusCode[1], 0)) status_set("TRIM"); /* Boost */ if (riello_test_bit(&DevData.StatusCode[1], 1)) status_set("BOOST"); /* Replace battery */ if (riello_test_bit(&DevData.StatusCode[2], 0)) status_set("RB"); /* Charging battery */ if (riello_test_bit(&DevData.StatusCode[2], 2)) status_set("CHRG"); status_commit(); dstate_dataok(); if (getextendedOK) { dstate_setinfo("output.L1.power", "%u", DevData.Pout1VA); dstate_setinfo("output.L2.power", "%u", DevData.Pout2VA); dstate_setinfo("output.L3.power", "%u", DevData.Pout3VA); dstate_setinfo("output.L1.realpower", "%u", DevData.Pout1W); dstate_setinfo("output.L2.realpower", "%u", DevData.Pout2W); dstate_setinfo("output.L3.realpower", "%u", DevData.Pout3W); dstate_setinfo("output.L1.current", "%u", DevData.Iout1); dstate_setinfo("output.L2.current", "%u", DevData.Iout2); dstate_setinfo("output.L3.current", "%u", DevData.Iout3); } poll_interval = 2; countlost = 0; /* if (get_ups_statuscode() != 0) upsdebugx(2, "Communication is lost"); else { }*/ /* * poll_interval = 2; */ }
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; }
/* normal idle loop - keep up with the current state of the UPS */ void upsdrv_updateinfo(void) { unsigned char c; unsigned int ob, lb; static unsigned int ob_state = 0, ob_last = 0, ob_ctr = 0; static unsigned int lb_state = 0, lb_last = 0, lb_ctr = 0; ob = lb = 0; /* the UPS connects RX to TX when on battery, so test for loopback */ ser_flush_in(upsfd, "", 0); c = ML_ONBATTERY; ser_send_char(upsfd, c); if (ser_get_char(upsfd, &c, 1, 0) == 1) { while (ser_get_char(upsfd, &c, 1, 0) == 1) continue; if (c == ML_ONBATTERY) ob = 1; } if (ser_get_dcd(upsfd)) lb = 1; /* state machine below to ensure status changes are debounced */ /* OB/OL state change: reset counter */ if (ob_last != ob) ob_ctr = 0; else ob_ctr++; upsdebugx(2, "OB: state %d last %d now %d ctr %d", ob_state, ob_last, ob, ob_ctr); if (ob_ctr >= DEBOUNCE) { if (ob != ob_state) { upsdebugx(2, "OB: toggling state"); if (ob_state == 0) ob_state = 1; else ob_state = 0; } } ob_last = ob; /* now do it again for LB */ /* state change: reset counter */ if (lb_last != lb) lb_ctr = 0; else lb_ctr++; upsdebugx(2, "LB: state %d last %d now %d ctr %d", lb_state, lb_last, lb, lb_ctr); if (lb_ctr >= DEBOUNCE) { if (lb != lb_state) { upsdebugx(2, "LB: toggling state"); if (lb_state == 0) lb_state = 1; else lb_state = 0; } } lb_last = lb; status_init(); if (ob_state == 1) status_set("OB"); /* on battery */ else status_set("OL"); /* on line */ if (lb_state == 1) status_set("LB"); /* low battery */ status_commit(); dstate_dataok(); }
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(); }
void upsdrv_updateinfo(void) { static int CommTry = COMM_TRIES; /* Comm loss counter */ char buffer[256]; /* Main response buffer */ char buffer2[32]; /* Conversion buffer */ char s; int RetValue; int timevalue; /* Start with EG/ON information */ ser_flush_in(upsfd,"",0); /*just in case*/ 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 != 0) && (CommTry == 0)) { ser_comm_fail("Oneac UPS Comm failure continues on port %s", device_path); } else if (RetValue != 0) { if (--CommTry == 0) { ser_comm_fail("Oneac UPS Comm failure on port %s",device_path); dstate_datastale(); } upsdebugx(2,"Oneac: Update serial comm retry value: %d", CommTry); return; } else { CommTry = COMM_TRIES; /* Reset serial retries */ s = buffer[12]; status_init(); alarm_init(); /*take care of the UPS status information*/ if (s == '@') { status_set("OL"); } else { if (s & 0x01) /* On Battery */ { status_set("OB"); } else { status_set("OL"); } if (s & 0x02) /* Low Battery */ status_set("LB"); if (s & 0x04) /* General fault */ { dstate_setinfo("ups.test.result","UPS Internal Failure"); } else { dstate_setinfo("ups.test.result","Normal"); } if (s & 0x08) /* Replace Battery */ status_set("RB"); /* if (s & 0x10) */ /* High Line */ if (s & 0x20) /* Unit is hot */ alarm_set("OVERHEAT"); } /*take care of the reason why the UPS last transferred to battery*/ switch (buffer[13]) { case XFER_BLACKOUT : dstate_setinfo("input.transfer.reason", "Blackout"); break; case XFER_LOW_VOLT : dstate_setinfo("input.transfer.reason", "Low Input Voltage"); break; case XFER_HI_VOLT : dstate_setinfo("input.transfer.reason", "High Input Voltage"); break; case NO_VALUE_YET : dstate_setinfo("input.transfer.reason", "No transfer yet."); break; default : upslogx(LOG_INFO,"Oneac: Unknown reason for UPS battery" " transfer [%c]", buffer[13]); } /* now update info for only the non-EG families of UPS*/ if (strncmp(UpsFamily, FAMILY_EG, FAMILY_SIZE) != 0) { dstate_setinfo("ups.load", "0%.2s",buffer+31); /* Output ON or OFF? */ if(buffer[27] == NO_VALUE_YET) status_set("OFF"); /*battery charge*/ if(buffer[10] == YES) dstate_setinfo("battery.charge", "0%.2s",buffer+33); else dstate_setinfo("battery.charge", "100"); EliminateLeadingZeroes (buffer+35, 3, buffer2, sizeof(buffer2)); dstate_setinfo("input.voltage", "%s",buffer2); EliminateLeadingZeroes (buffer+38, 3, buffer2, sizeof(buffer2)); dstate_setinfo("input.voltage.minimum", "%s",buffer2); EliminateLeadingZeroes (buffer+41, 3, buffer2, sizeof(buffer2)); dstate_setinfo("input.voltage.maximum", "%s",buffer2); EliminateLeadingZeroes (buffer+44, 3, buffer2, sizeof(buffer2)); dstate_setinfo("output.voltage", "%s",buffer2); if (buffer[15] == NO_VALUE_YET) { dstate_delinfo("ups.timer.shutdown"); } else { /* A shutdown is underway! */ status_set("FSD"); if(buffer[15] != HIGH_COUNT) { EliminateLeadingZeroes (buffer+15, 3, buffer2, sizeof(buffer2)); dstate_setinfo("ups.timer.shutdown", "%s", buffer2); } else { dstate_setinfo("ups.timer.shutdown", "999"); } } if (buffer[47] == YES) status_set("BOOST"); } /* Now update info for only the OZ/OB families of UPS */ if ((strncmp(UpsFamily, FAMILY_OZ, FAMILY_SIZE) == 0) || (strncmp(UpsFamily, FAMILY_OB, FAMILY_SIZE) == 0)) { ser_flush_in(upsfd,"",0); /*just in case*/ ser_send (upsfd,"%c%s",GETX_ALL_1,COMMAND_END); RetValue = OneacGetResponse (buffer, sizeof(buffer), GETX_ALL1_RESP_SIZE); if(RetValue) { if (--CommTry == 0) { ser_comm_fail("Oneac (OZ) UPS Comm failure on port %s", device_path); dstate_datastale(); } upsdebugx(2,"Oneac: " "Update (OZ) serial comm retry value: %d", CommTry); } else { CommTry = COMM_TRIES; /* Reset count */ EliminateLeadingZeroes (buffer+57, 5, buffer2, sizeof(buffer2)); dstate_setinfo("ups.realpower", "%s",buffer2); dstate_setinfo("input.frequency", "%.2s.%c", buffer+42,buffer[44]); dstate_setinfo("output.frequency", "%.2s.%c", buffer+76, buffer[78]); EliminateLeadingZeroes (buffer+29, 3, buffer2, sizeof(buffer2)); dstate_setinfo("battery.voltage", "%s.%c",buffer2, buffer[32]); dstate_setinfo("ups.temperature", "%.2s",buffer+13); dstate_setinfo("ups.load", "%.3s",buffer+73); strncpy(buffer2, buffer+19, 4); buffer2[4]='\0'; timevalue = atoi(buffer2) * 60; /* Change mins to secs */ dstate_setinfo("battery.runtime", "%d",timevalue); /* Now some individual requests... */ /* Battery replace date */ ser_send (upsfd,"%c%s",GETX_BATT_REPLACED,COMMAND_END); if(!OneacGetResponse (buffer, sizeof(buffer), GETX_DATE_RESP_SIZE)) dstate_setinfo("battery.date", "%.6s (yymmdd)", buffer); /* Low and high output trip points */ ser_send (upsfd,"%c%s",GETX_LOW_OUT_ALLOW,COMMAND_END); if(!OneacGetResponse (buffer, sizeof(buffer), GETX_ALLOW_RESP_SIZE)) { EliminateLeadingZeroes (buffer, 3, buffer2,sizeof(buffer2)); dstate_setinfo("input.transfer.low", "%s", buffer2); } ser_send (upsfd,"%c%s",GETX_HI_OUT_ALLOW,COMMAND_END); if(!OneacGetResponse (buffer, sizeof(buffer), GETX_ALLOW_RESP_SIZE)) dstate_setinfo("input.transfer.high", "%s", buffer); /* Restart delay */ ser_send (upsfd,"%c%s",GETX_RESTART_DLY,COMMAND_END); if(!OneacGetResponse (buffer, sizeof(buffer), GETX_RSTRT_RESP_SIZE)) { EliminateLeadingZeroes (buffer, 4, buffer2, sizeof(buffer2)); dstate_setinfo("ups.delay.start", "%s", buffer2); } /* Buzzer state */ ser_send (upsfd,"%s%s",GETX_BUZZER_WHAT,COMMAND_END); if(!OneacGetResponse (buffer, sizeof(buffer), 1)) { switch (buffer[0]) { case BUZZER_ENABLED : dstate_setinfo("ups.beeper.status", "enabled"); break; case BUZZER_DISABLED : dstate_setinfo("ups.beeper.status", "disabled"); break; case BUZZER_MUTED : dstate_setinfo("ups.beeper.status", "muted"); break; default : dstate_setinfo("ups.beeper.status", "enabled"); } } /* Auto start setting */ ser_send (upsfd,"%s%s",GETX_AUTO_START,COMMAND_END); if(!OneacGetResponse (buffer, sizeof(buffer), 1)) { if (buffer[0] == '0') dstate_setinfo("ups.start.auto", "yes"); else dstate_setinfo("ups.start.auto", "no"); } /* Low Batt at time */ ser_send (upsfd,"%c%s",GETX_LOW_BATT_TIME,COMMAND_END); if(!OneacGetResponse (buffer, sizeof(buffer), 2)) { strncpy(buffer2, buffer, 2); buffer2[2]='\0'; timevalue = atoi(buffer2) * 60; /* Mins to secs */ dstate_setinfo("battery.runtime.low", "%d",timevalue); } /* Shutdown timer */ ser_send (upsfd,"%c%s",GETX_SHUTDOWN,COMMAND_END); if(!OneacGetResponse (buffer, sizeof(buffer), GETX_SHUTDOWN_RESP_SIZE)) { /* ON would have handled NO_VALUE_YET and setting FSD * above so only deal with counter value here. */ if (buffer[0] != NO_VALUE_YET) { EliminateLeadingZeroes (buffer, 5, buffer2, sizeof(buffer2)); dstate_setinfo("ups.timer.shutdown", "%s", buffer2); } } /* Restart timer */ ser_send (upsfd,"%s%s",GETX_RESTART_COUNT,COMMAND_END); if(!OneacGetResponse (buffer, sizeof(buffer), GETX_RSTRT_RESP_SIZE)) { if (atoi(buffer) == 0) { dstate_delinfo("ups.timer.start"); } else { EliminateLeadingZeroes (buffer, 4, buffer2, sizeof(buffer2)); dstate_setinfo("ups.timer.start", "%s", buffer2); } } } } alarm_commit(); status_commit(); /* If the comm retry counter is zero then datastale has been set. * We don't want to set dataok or ser_comm_good if that is the case. */ if (CommTry != 0) { dstate_dataok(); ser_comm_good(); } } }
void upsdrv_updateinfo(void) { char fstring[512]; if (! fc.valid) { fprintf(stderr, "upsupdate run before ups_ident() read ups config\n"); assert(0); } if (execute("f\r", fstring, sizeof(fstring)) > 0) { int inverter=0, charger=0, vin=0, vout=0, btimeleft=0, linestat=0, alstat=0, vaout=0; double ampsout=0.0, vbatt=0.0, battpercent=0.0, loadpercent=0.0, hstemp=0.0, acfreq=0.0, ambtemp=0.0; char tmp[16]; /* Inverter status. 0=off 1=on */ memcpy(tmp, fstring+16, 2); tmp[2] = '\0'; inverter = atoi(tmp); /* Charger status. 0=off 1=on */ memcpy(tmp, fstring+18, 2); tmp[2] = '\0'; charger = atoi(tmp); /* Input Voltage. integer number */ memcpy(tmp, fstring+24, 4); tmp[4] = '\0'; vin = atoi(tmp); /* Output Voltage. integer number */ memcpy(tmp, fstring+28, 4); tmp[4] = '\0'; vout = atoi(tmp); /* Iout. int times 10 */ memcpy(tmp, fstring+36, 4); tmp[4] = '\0'; ampsout = ((double)(atoi(tmp)) / 10.0); /* Battery voltage. int times 10 */ memcpy(tmp, fstring+50, 4); tmp[4] = '\0'; vbatt = ((double)(atoi(tmp)) / 10.0); /* Volt-amps out. int */ memcpy(tmp, fstring+40, 6); tmp[6] = '\0'; vaout = atoi(tmp); /* Line status. Bitmask */ memcpy(tmp, fstring+72, 2); tmp[2] = '\0'; linestat = atoi(tmp); /* Alarm status reg 1. Bitmask */ memcpy(tmp, fstring+20, 2); tmp[2] = '\0'; alstat = atoi(tmp); /* Alarm status reg 2. Bitmask */ memcpy(tmp, fstring+22, 2); tmp[2] = '\0'; alstat = alstat | (atoi(tmp) << 8); /* AC line frequency */ memcpy(tmp, fstring+54, 4); tmp[4]= '\0'; acfreq = ((double)(atoi(tmp)) / 100.0); /* Runtime remaining */ memcpy(tmp, fstring+58, 4); tmp[4]= '\0'; btimeleft = atoi(tmp); /* UPS Temperature */ memcpy(tmp, fstring+62, 4); tmp[4]= '\0'; ambtemp = (double)(atoi(tmp)); /* Percent Load */ switch(fc.model) { case ME3100: if (execute("d 16\r", fstring, sizeof(fstring)) > 0) { int l; sscanf(fstring, "16 FullLoad%% %d", &l); loadpercent = (double) l; } break; case RE1800: if (execute("d 16\r", fstring, sizeof(fstring)) > 0) { int l; sscanf(fstring, "16 FullLoad%% %d", &l); loadpercent = (double) l; } if (execute("d 12\r", fstring, sizeof(fstring)) > 0) { int l; sscanf(fstring, "12 HS Temp %dC", &l); hstemp = (double) l; } break; case MD1KVA: if (execute("d 22\r", fstring, sizeof(fstring)) > 0) { int l; sscanf(fstring, "22 FullLoad%% %d", &l); loadpercent = (double) l; } break; default: /* Will never happen, caught in upsdrv_initups() */ fatalx(EXIT_FAILURE, "Unknown model in upsdrv_updateinfo()"); } /* Compute battery percent left based on battery voltages. */ battpercent = ((vbatt - fc.emptyvolts) / (fc.fullvolts - fc.emptyvolts) * 100.0); if (battpercent < 0.0) battpercent = 0.0; else if (battpercent > 100.0) battpercent = 100.0; /* Compute status string */ { int lowbatt, overload, replacebatt, boosting, trimming; lowbatt = alstat & (1<<1); overload = alstat & (1<<6); replacebatt = alstat & (1<<10); boosting = inverter && (linestat & (1<<2)) && (vin < 115); trimming = inverter && (linestat & (1<<2)) && (vin > 115); status_init(); if (inverter) status_set("OB"); else status_set("OL"); if (lowbatt) status_set("LB"); if (trimming) status_set("TRIM"); if (boosting) status_set("BOOST"); if (replacebatt) status_set("RB"); if (overload) status_set("OVER"); status_commit(); } if (debugging) { fprintf(stderr, "Poll: inverter %d charger %d vin %d vout %d vaout %d btimeleft %d\n", inverter, charger, vin, vout, vaout, btimeleft); fprintf(stderr, " ampsout %5.1f vbatt %5.1f batpcnt %5.1f loadpcnt %5.1f upstemp %5.1f acfreq %5.2f ambtemp %5.1f\n", ampsout, vbatt, battpercent, loadpercent, hstemp, acfreq, ambtemp); } /* Stuff information into info structures */ dstate_setinfo("input.voltage", "%05.1f", (double)vin); dstate_setinfo("output.voltage", "%05.1f", (double)vout); dstate_setinfo("battery.charge", "%02.1f", battpercent); dstate_setinfo("ups.load", "%02.1f", loadpercent); dstate_setinfo("battery.voltage", "%02.1f", vbatt); dstate_setinfo("input.frequency", "%05.2f", (double)acfreq); dstate_setinfo("ups.temperature", "%05.1f", (double)hstemp); dstate_setinfo("battery.runtime", "%d", btimeleft); dstate_setinfo("ambient.temperature", "%05.1f", (double)ambtemp); dstate_dataok(); /* Tim: With out this return, it always falls over to the datastate() at the end of the function */ return; } else { dstate_datastale(); } /* if (execute("f\r", fstring, sizeof(fstring)) > 0) */ dstate_datastale(); return; }
void upsdrv_updateinfo(void) { char response[MAX_RESPONSE_LENGTH]; char *ptr, *ptr2; int i; int flags; int contacts_set; int low_battery; status_init(); if (do_command(POLL, STATUS_OUTPUT, "", response) <= 0) { dstate_datastale(); return; } ptr = field(response, 0); /* require output status field to exist */ if (!ptr) { dstate_datastale(); return; } switch (atoi(ptr)) { case 0: status_set("OL"); break; case 1: status_set("OB"); break; case 2: status_set("BYPASS"); break; case 3: status_set("OL"); status_set("TRIM"); break; case 4: status_set("OL"); status_set("BOOST"); break; case 5: status_set("BYPASS"); break; case 6: break; case 7: status_set("OFF"); break; default: break; } ptr = field(response, 6); if (ptr) dstate_setinfo("ups.load", "%d", atoi(ptr)); ptr = field(response, 3); if (ptr) dstate_setinfo("output.voltage", "%03.1f", (double) atoi(ptr) / 10.0); ptr = field(response, 1); if (ptr) dstate_setinfo("output.frequency", "%03.1f", (double) atoi(ptr) / 10.0); ptr = field(response, 4); if (ptr) dstate_setinfo("output.current", "%03.1f", (double) atoi(ptr) / 10.0); low_battery = 0; if (do_command(POLL, STATUS_BATTERY, "", response) <= 0) { dstate_datastale(); return; } ptr = field(response, 0); if (ptr && atoi(ptr) == 2) status_set("RB"); ptr = field(response, 1); if (ptr && atoi(ptr)) low_battery = 1; ptr = field(response, 8); if (ptr) dstate_setinfo("battery.temperature", "%d", atoi(ptr)); ptr = field(response, 9); if (ptr) { dstate_setinfo("battery.charge", "%d", atoi(ptr)); ptr2 = getval("lowbatt"); if (ptr2 && atoi(ptr2) > 0 && atoi(ptr2) <= 99 && atoi(ptr) <= atoi(ptr2)) low_battery = 1; } ptr = field(response, 6); if (ptr) dstate_setinfo("battery.voltage", "%03.1f", (double) atoi(ptr) / 10.0); ptr = field(response, 7); if (ptr) dstate_setinfo("battery.current", "%03.1f", (double) atoi(ptr) / 10.0); if (low_battery) status_set("LB"); if (do_command(POLL, STATUS_ALARM, "", response) <= 0) { dstate_datastale(); return; } ptr = field(response, 3); if (ptr && atoi(ptr)) status_set("OVER"); if (do_command(POLL, STATUS_INPUT, "", response) > 0) { ptr = field(response, 2); if (ptr) dstate_setinfo("input.voltage", "%03.1f", (double) atoi(ptr) / 10.0); ptr = field(response, 1); if (ptr) dstate_setinfo("input.frequency", "%03.1f", (double) atoi(ptr) / 10.0); } if (do_command(POLL, TEST_RESULT, "", response) > 0) { int r; size_t trsize; r = atoi(response); trsize = sizeof(test_result_names) / sizeof(test_result_names[0]); if ((r < 0) || (r >= (int) trsize)) r = 0; dstate_setinfo("ups.test.result", "%s", test_result_names[r]); } if (do_command(POLL, ENVIRONMENT_INFORMATION, "", response) > 0) { ptr = field(response, 0); if (ptr) dstate_setinfo("ambient.temperature", "%d", atoi(ptr)); ptr = field(response, 1); if (ptr) dstate_setinfo("ambient.humidity", "%d", atoi(ptr)); flags = 0; contacts_set = 0; for (i = 0; i < 4; i++) { ptr = field(response, 2 + i); if (ptr) { contacts_set = 1; if (*ptr == '1') flags |= 1 << i; } } if (contacts_set) dstate_setinfo("ups.contacts", "%02X", flags); } /* if we are here, status is valid */ status_commit(); dstate_dataok(); }
void upsdrv_updateinfo(void) { CFPropertyListRef power_dictionary; CFStringRef power_source_state; CFNumberRef battery_voltage, battery_runtime; CFNumberRef current_capacity; CFBooleanRef is_charging; double max_capacity_value = 100.0, current_capacity_value; upsdebugx(1, "upsdrv_updateinfo()"); power_dictionary = copy_power_dictionary( g_power_key ); assert(power_dictionary); /* TODO: call dstate_datastale()? */ status_init(); /* Retrieve OL/OB state */ power_source_state = CFDictionaryGetValue(power_dictionary, CFSTR(kIOPSPowerSourceStateKey)); assert(power_source_state); CFRetain(power_source_state); upsdebugx(3, "Power Source State:"); if(nut_debug_level >= 3) CFShow(power_source_state); if(!CFStringCompare(power_source_state, CFSTR(kIOPSACPowerValue), 0)) { status_set("OL"); } else { status_set("OB"); } CFRelease(power_source_state); /* Retrieve CHRG state */ is_charging = CFDictionaryGetValue(power_dictionary, CFSTR(kIOPSIsChargingKey)); if(is_charging) { Boolean is_charging_value; is_charging_value = CFBooleanGetValue(is_charging); if(is_charging_value) { status_set("CHRG"); } } status_commit(); /* Retrieve battery voltage */ battery_voltage = CFDictionaryGetValue(power_dictionary, CFSTR(kIOPSVoltageKey)); if(battery_voltage) { int battery_voltage_value; CFNumberGetValue(battery_voltage, kCFNumberIntType, &battery_voltage_value); upsdebugx(2, "battery_voltage = %d mV", battery_voltage_value); dstate_setinfo("battery.voltage", "%.3f", battery_voltage_value/1000.0); } /* Retrieve battery runtime */ battery_runtime = CFDictionaryGetValue(power_dictionary, CFSTR(kIOPSTimeToEmptyKey)); if(battery_runtime) { double battery_runtime_value; CFNumberGetValue(battery_runtime, kCFNumberDoubleType, &battery_runtime_value); upsdebugx(2, "battery_runtime = %.f minutes", battery_runtime_value); if(battery_runtime_value > 0) { dstate_setinfo("battery.runtime", "%d", (int)(battery_runtime_value*60)); } else { dstate_delinfo("battery.runtime"); } } else { dstate_delinfo("battery.runtime"); } /* Retrieve current capacity */ current_capacity = CFDictionaryGetValue(power_dictionary, CFSTR(kIOPSCurrentCapacityKey)); if(current_capacity) { CFNumberGetValue(current_capacity, kCFNumberDoubleType, ¤t_capacity_value); upsdebugx(2, "Current Capacity = %.f/%.f units", current_capacity_value, max_capacity_value); if(max_capacity_value > 0) { dstate_setinfo("battery.charge", "%.f", 100.0 * current_capacity_value / max_capacity_value); } } /* TODO: it should be possible to set poll_interval (and maxage in the * server) to an absurdly large value, and use notify(3) to get * updates. */ /* * poll_interval = 2; */ dstate_dataok(); CFRelease(power_dictionary); }
/* 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(); }
void upsdrv_updateinfo(void) { int res, int_num; #ifdef EXTRADATA int day, hour, minute; #endif float float_num; long int long_num; unsigned char my_answer[255]; /* GET Output data */ res = command_read_sequence(UPS_OUTPUT_DATA, my_answer); if (res < 0) { printf("Could not communicate with the ups"); dstate_datastale(); } else { /* Active power */ int_num = get_word(&my_answer[1]); if (nominal_power != 0) { float_num = (float)((int_num * 100)/nominal_power); dstate_setinfo("ups.load", "%2.1f", float_num); } else { dstate_setinfo("ups.load", "%s", "not available"); } #ifdef EXTRADATA dstate_setinfo("output.power", "%d", int_num); #endif /* voltage */ int_num = get_word(&my_answer[3]); if (int_num > 0) dstate_setinfo("output.voltage", "%d", int_num); if (int_num == -1) dstate_setinfo("output.voltage", "%s", "overrange"); if (int_num == -2) dstate_setinfo("output.voltage", "%s", "not available"); /* current */ float_num = get_word(&my_answer[5]); if (float_num == -1) dstate_setinfo("output.current", "%s", "overrange"); if (float_num == -2) dstate_setinfo("output.current", "%s", "not available"); if (float_num > 0) { float_num = (float)(float_num/10); dstate_setinfo("output.current", "%2.2f", float_num); } #ifdef EXTRADATA /* peak current */ float_num = get_word(&my_answer[7]); if (float_num == -1) dstate_setinfo("output.current.peak", "%s", "overrange"); if (float_num == -2) dstate_setinfo("output.current.peak", "%s", "not available"); if (float_num > 0) { float_num = (float)(float_num/10); dstate_setinfo("output.current.peak", "%2.2f", float_num); } #endif } /* GET Input data */ res = command_read_sequence(UPS_INPUT_DATA, my_answer); if (res < 0){ printf("Could not communicate with the ups"); dstate_datastale(); } else { #ifdef EXTRADATA /* Active power */ int_num = get_word(&my_answer[1]); if (int_num > 0) dstate_setinfo("input.power", "%d", int_num); if (int_num == -1) dstate_setinfo("input.power", "%s", "overrange"); if (int_num == -2) dstate_setinfo("input.power", "%s", "not available"); #endif /* voltage */ int_num = get_word(&my_answer[3]); if (int_num > 0) dstate_setinfo("input.voltage", "%d", int_num); if (int_num == -1) dstate_setinfo("input.voltage", "%s", "overrange"); if (int_num == -2) dstate_setinfo("input.voltage", "%s", "not available"); #ifdef EXTRADATA /* current */ float_num = get_word(&my_answer[5]); if (float_num == -1) dstate_setinfo("input.current", "%s", "overrange"); if (float_num == -2) dstate_setinfo("input.current", "%s", "not available"); if (float_num > 0) { float_num = (float)(float_num/10); dstate_setinfo("input.current", "%2.2f", float_num); } /* peak current */ float_num = get_word(&my_answer[7]); if (float_num == -1) dstate_setinfo("input.current.peak", "%s", "overrange"); if (float_num == -2) dstate_setinfo("input.current.peak", "%s", "not available"); if (float_num > 0) { float_num = (float)(float_num/10); dstate_setinfo("input.current.peak", "%2.2f", float_num); } #endif } /* GET Battery data */ res = command_read_sequence(UPS_BATTERY_DATA, my_answer); if (res < 0) { printf("Could not communicate with the ups"); dstate_datastale(); } else { /* Actual value */ float_num = get_word(&my_answer[1]); float_num = (float)(float_num/10); dstate_setinfo("battery.voltage", "%2.2f", float_num); #ifdef EXTRADATA /* reserve threshold */ float_num = get_word(&my_answer[3]); float_num = (float)(float_num/10); dstate_setinfo("battery.voltage.low", "%2.2f", float_num); /* exhaust threshold */ float_num = get_word(&my_answer[5]); float_num = (float)(float_num/10); dstate_setinfo("battery.voltage.exhaust", "%2.2f", float_num); #endif } #ifdef EXTRADATA /* GET history data */ res = command_read_sequence(UPS_HISTORY_DATA, my_answer); if (res < 0) { printf("Could not communicate with the ups"); dstate_datastale(); } else { /* ups total runtime */ long_num = get_long(&my_answer[1]); day = (int)(long_num / 86400); long_num -= (long)(day*86400); hour = (int)(long_num / 3600); long_num -= (long)(hour*3600); minute = (int)(long_num / 60); long_num -= (minute*60); dstate_setinfo("ups.total.runtime", "%d days %dh %dm %lds", day, hour, minute, long_num); /* ups inverter runtime */ long_num = get_long(&my_answer[5]); day = (int)(long_num / 86400); long_num -= (long)(day*86400); hour = (int)(long_num / 3600); long_num -= (long)(hour*3600); minute = (int)(long_num / 60); long_num -= (minute*60); dstate_setinfo("ups.inverter.runtime", "%d days %dh %dm %lds", day, hour, minute, long_num); /* ups inverter interventions */ dstate_setinfo("ups.inverter.interventions", "%d", get_word(&my_answer[9])); /* battery full discharges */ dstate_setinfo("battery.full.discharges", "%d", get_word(&my_answer[11])); /* ups bypass / stabilizer interventions */ int_num = get_word(&my_answer[13]); if (int_num == -2) dstate_setinfo("ups.bypass.interventions", "%s", "not avaliable"); if (int_num >= 0) dstate_setinfo("ups.bypass.interventions", "%d", int_num); /* ups overheatings */ int_num = get_word(&my_answer[15]); if (int_num == -2) dstate_setinfo("ups.overheatings", "%s", "not avalilable"); if (int_num >= 0) dstate_setinfo("ups.overheatings", "%d", int_num); } #endif /* GET times on battery */ res = command_read_sequence(UPS_GET_TIMES_ON_BATTERY, my_answer); if (res < 0) { printf("Could not communicate with the ups"); dstate_datastale(); } else { autorestart = my_answer[5]; } /* GET schedule */ res = command_read_sequence(UPS_GET_SCHEDULING, my_answer); if (res < 0) { printf("Could not communicate with the ups"); dstate_datastale(); } else { /* time remaining to shutdown */ long_num = get_long(&my_answer[1]); if (long_num == -1) { dstate_setinfo("ups.delay.shutdown", "%d", 120); } else { dstate_setinfo("ups.delay.shutdown", "%ld", long_num); } /* time remaining to restart */ long_num = get_long(&my_answer[5]); if (long_num == -1) { dstate_setinfo("ups.delay.start", "%d", 0); } else { dstate_setinfo("ups.delay.start", "%ld", long_num); } } /* GET ups status */ res = command_read_sequence(UPS_STATUS, my_answer); if (res < 0) { printf("Could not communicate with the ups"); dstate_datastale(); } else { /* ups temperature */ my_answer[3] -=128; if (my_answer[3] > 0) { dstate_setinfo("ups.temperature", "%d", my_answer[3]); } else { dstate_setinfo("ups.temperature", "%s", "not available"); } /* Status */ status_init(); switch (my_answer[1]) { /* byte 1 = STATUS */ case 0x00: status_set("OL"); /* running on mains power */ break; case 0x01: status_set("OB"); /* running on battery power */ break; case 0x02: status_set("LB"); /* battery reserve */ break; case 0x03: /* bypass engaged */ case 0x04: /* manual bypass engaged */ status_set("BY"); break; default: printf("status unknown \n"); break; } switch (my_answer[2]) { /* byte 2 = FAULTS */ case 0x00: /* all right */ break; case 0x01: /* overload */ status_set("OVER"); break; case 0x02: /* overheat */ break; case 0x03: /* hardware fault */ break; case 0x04: /* battery charger failure (overcharging) */ break; case 0x05: /* replace batteries */ status_set("RB"); break; default: printf("status unknown \n"); break; } status_commit(); dstate_dataok(); } return; }
/* for dummy mode * parse the definition file and process its content */ static int parse_data_file(int upsfd) { char fn[SMALLBUF]; char *ptr, var_value[MAX_STRING_SIZE]; int value_args = 0, counter; time_t now; time(&now); upsdebugx(1, "entering parse_data_file()"); if (now < next_update) { upsdebugx(1, "leaving (paused)..."); return 1; } /* initialise everything, to loop back at the beginning of the file */ if (ctx == NULL) { ctx = (PCONF_CTX_t *)xmalloc(sizeof(PCONF_CTX_t)); if (device_path[0] == '/') snprintf(fn, sizeof(fn), "%s", device_path); else snprintf(fn, sizeof(fn), "%s/%s", confpath(), device_path); pconf_init(ctx, upsconf_err); if (!pconf_file_begin(ctx, fn)) fatalx(EXIT_FAILURE, "Can't open dummy-ups definition file %s: %s", fn, ctx->errmsg); } /* Reset the next call time, so that we can loop back on the file * if there is no blocking action (ie TIMER) until the end of the file */ next_update = -1; /* Now start or continue parsing... */ while (pconf_file_next(ctx)) { if (pconf_parse_error(ctx)) { upsdebugx(2, "Parse error: %s:%d: %s", fn, ctx->linenum, ctx->errmsg); continue; } /* Check if we have something to process */ if (ctx->numargs < 1) continue; /* Process actions (only "TIMER" ATM) */ if (!strncmp(ctx->arglist[0], "TIMER", 5)) { /* TIMER <seconds> will wait "seconds" before * continuing the parsing */ int delay = atoi (ctx->arglist[1]); time(&next_update); next_update += delay; upsdebugx(1, "suspending execution for %i seconds...", delay); break; } /* Remove ":" suffix, after the variable name */ if ((ptr = strchr(ctx->arglist[0], ':')) != NULL) *ptr = '\0'; upsdebugx(3, "parse_data_file: variable \"%s\" with %d args", ctx->arglist[0], (int)ctx->numargs); /* Skip the driver.* collection data */ if (!strncmp(ctx->arglist[0], "driver.", 7)) { upsdebugx(2, "parse_data_file: skipping %s", ctx->arglist[0]); continue; } /* From there, we get varname in arg[0], and values in other arg[1...x] */ /* special handler for status */ if (!strncmp( ctx->arglist[0], "ups.status", 10)) { status_init(); for (counter = 1, value_args = ctx->numargs ; counter < value_args ; counter++) { status_set(ctx->arglist[counter]); } status_commit(); } else { for (counter = 1, value_args = ctx->numargs ; counter < value_args ; counter++) { if (counter == 1) /* don't append the first space separator */ snprintf(var_value, sizeof(var_value), "%s", ctx->arglist[counter]); else snprintfcat(var_value, sizeof(var_value), " %s", ctx->arglist[counter]); } if (setvar(ctx->arglist[0], var_value) == STAT_SET_UNKNOWN) { upsdebugx(2, "parse_data_file: can't add \"%s\" with value \"%s\"\nError: %s", ctx->arglist[0], var_value, ctx->errmsg); } else { upsdebugx(3, "parse_data_file: added \"%s\" with value \"%s\"", ctx->arglist[0], var_value); } } } /* Cleanup parseconf if there is no pending action */ if (next_update == -1) { pconf_finish(ctx); free(ctx); ctx=NULL; } return 1; }
void upsdrv_updateinfo(void) { int ret, errors = 0; /* We really should be dealing with alarms through a separate callback, so that we can keep the * processing of alarms and polling for data separated. Currently, this isn't supported by the * driver main body, so we'll have to revert to polling each time we're called, unless the * socket indicates we're no longer connected. */ if (testvar("subscribe")) { char buf[LARGEBUF]; ret = ne_sock_read(sock, buf, sizeof(buf)); if (ret > 0) { /* alarm message received */ ne_xml_parser *parser = ne_xml_create(); upsdebugx(2, "%s: ne_sock_read(%d bytes) => %s", __func__, ret, buf); ne_xml_push_handler(parser, subdriver->startelm_cb, subdriver->cdata_cb, subdriver->endelm_cb, NULL); ne_xml_parse(parser, buf, strlen(buf)); ne_xml_destroy(parser); time(&lastheard); } else if ((ret == NE_SOCK_TIMEOUT) && (difftime(time(NULL), lastheard) < 180)) { /* timed out */ upsdebugx(2, "%s: ne_sock_read(timeout)", __func__); } else { /* connection closed or unknown error */ upslogx(LOG_ERR, "NSM connection with '%s' lost", uri.host); upsdebugx(2, "%s: ne_sock_read(%d) => %s", __func__, ret, ne_sock_error(sock)); ne_sock_close(sock); if (netxml_alarm_subscribe(subdriver->subscribe) == NE_OK) { extrafd = ne_sock_fd(sock); time(&lastheard); return; } dstate_datastale(); extrafd = -1; return; } } /* get additional data */ ret = netxml_get_page(subdriver->getobject); if (ret != NE_OK) { errors++; } ret = netxml_get_page(subdriver->summary); if (ret != NE_OK) { errors++; } if (errors > 1) { dstate_datastale(); return; } status_init(); alarm_init(); netxml_alarm_set(); alarm_commit(); netxml_status_set(); status_commit(); dstate_dataok(); }