1
/* The attached microdowell.h has also textual details about what this * program does, the
2
copyrights and such. */
8
static int ups_model_ok (char *buf, unsigned buflen);
9
static int polling_ok (char *buf, unsigned buflen);
10
static int read_raw_data (int upsfd, char *buf, int buflen);
12
void set_flag (int *val, int flag)
14
*val = (*val |= flag);
17
void clear_flag (int *val, int flag)
19
*val = (*val ^= (*val & flag));
22
int is_set (int num, int flag)
24
return ((num & flag) == flag);
27
static int setupstime ()
31
unsigned char upshour;
34
timeptr = localtime (&now);
36
if (upssendchar (CMD_SETTIMER) != 1)
39
upshour = (unsigned char) ((timeptr->tm_wday - 1) * 24 + timeptr->tm_hour);
40
if (upssendchar (upshour) != 1)
43
if (upssendchar ((unsigned char)timeptr->tm_min) != 1)
46
if (upssendchar ((unsigned char)timeptr->tm_sec) != 1)
53
/* power down the attached load immediately */
54
static int forceshutdown (unsigned int sddelay)
58
printf ("Initiating forced UPS shutdown!\n");
60
if (upssendchar (CMD_SCHEDULING) != 1)
65
if (upssendchar (data) != 1)
70
if (upssendchar (data) != 1)
75
if (upssendchar (data) != 1)
81
if ((myups.upsmodel > 21) && (myups.upsmodel <100))
82
sddelay = sddelay / 2 + 1;
83
else if (myups.upsmodel > 130)
84
sddelay = sddelay / 4 + 1;
86
data = (unsigned char)sddelay;
87
if (upssendchar (data) != 1)
92
if (upssendchar (data) != 1)
96
if (upssendchar (CMD_STDBY) != 1)
99
if (is_set(myups.status, ST_ONBATT)) {
100
if (upssendchar (CMD_BEND) != 1)
108
static void help (const char *prog)
112
"\t%s [-d <num>] -k <device>\n"
113
"\t%s [-l <num>] [-b <num>] <device>\n", prog, prog, prog);
115
" -h - display this help\n"
117
" -d <num> - wait <num> seconds after sending shutdown command\n"
118
" -k - force shutdown\n"
120
" -l <num> - line voltage. Default is 230 (volts)\n"
121
" -b <num> - battery run time (s) \n"
123
" <device> - /dev entry corresponding to UPS port\n"
128
static void initinfo (char *ident, char *model, char *serial_num)
130
unsigned char i, ret;
132
char raw_data[NUM_OF_BYTES_FROM_UPS];
134
create_info(INFO_MAX, SHMOK);
136
/* write constant data for this model */
138
addinfo (INFO_MFR, "MicroDowell", FLAG_STRING, 12);
140
for (i = 0; (i < 5) && (ret0 == 0); i++)
142
if (upssendchar (SEND_MODEL) != 1) {
143
/* upslogx(LOG_NOTICE, "%s writing error", argv[0]); */
145
ret = read_raw_data(upsfd, raw_data, NUM_MODEL_BYTES);
146
ret0 = ups_model_ok(raw_data, ret);
150
printf ("Unable to identify MicroDowell UPS connected: %d \n",ret0);
151
fatalx("Unable to identify MicroDowell UPS connected");
153
myups.upsmodel = ret0;
155
for (i = 0; (i < 5) && (ret0 == 0); i++)
157
if (upssendchar (SEND_DATA) != 1) {
158
/* upslogx(LOG_NOTICE, "%s writing error", argv[0]); */
160
ret = read_raw_data(upsfd, raw_data, NUM_POLLING_BYTES);
161
ret0 = polling_ok(raw_data, ret);
167
printf ("Unable to communicate with MicroDowell UPS connected. \n");
168
fatalx("Unable to communicate with MicroDowell UPS connected");
170
printf ("Communication with MicroDowell UPS started. \n");
173
/* add other things to monitor */
175
addinfo (INFO_ACFREQ, "", 0, 0);
176
addinfo (INFO_BATTVOLT, "", 0, 0);
177
addinfo (INFO_LOADPCT, "", 0, 0);
178
addinfo (INFO_STATUS, "", 0, 0);
179
addinfo (INFO_UTILITY, "", 0, 0);
180
addinfo (INFO_UPSTEMP, "", 0, 0);
182
/* now add the instant commands */
184
addinfo (INFO_INSTCMD, "", 0, CMD_ON);
185
addinfo (INFO_INSTCMD, "", 0, CMD_OFF);
186
addinfo (INFO_INSTCMD, "", 0, CMD_BTEST1);
188
updateinfo (line_voltage, raw_data);
191
void instcmd (int auxcmd, int dlen, char *data)
193
/* TODO: reply to upsd? */
200
if (upssendchar (CMD_BATTEST) != 1)
201
printf ("Unable to start battery test \n");
204
upslogx(LOG_INFO, "instcmd: unknown type 0x%04x",
209
static int ups_model_ok (char *buf, unsigned buflen)
214
if ((buflen==NUM_MODEL_BYTES) && (buf[0]==91) &&
215
(buf[NUM_MODEL_BYTES-1]==93) && (buf[1]==10))
217
if ((buf[2] == 'S') && (buf[3] == 'H'))
219
upsRelease = (buf[4] - '0') * 10 + buf[6] - '0';
221
addinfo (INFO_MODEL, "BBox Pro PnP", FLAG_STRING, 12);
223
addinfo (INFO_MODEL, "BBox Pro USB", FLAG_STRING, 12);
224
sprintf (upsSerial, "SH%c.%c", buf[4], buf[6]);
225
addinfo (INFO_SERIAL, upsSerial, FLAG_STRING, 5);
226
return (100 + upsRelease);
228
else if ((buf[2] == 'M') && (buf[3] == 'D'))
230
upsRelease = (buf[4] - '0') * 10 + buf[6] - '0';
232
addinfo (INFO_MODEL, "BBox Interactive PnP", FLAG_STRING, 20);
234
addinfo (INFO_MODEL, "BBox Interactive USB", FLAG_STRING, 20);
235
sprintf (upsSerial, "MD%c.%c", buf[4], buf[6]);
236
addinfo (INFO_SERIAL, upsSerial, FLAG_STRING, 5);
239
else if ((buf[2] == 'B') && (buf[3] == '5'))
241
upsRelease = (buf[4] - '0') * 10 + buf[6] - '0';
242
addinfo (INFO_MODEL, "HiBox USB", FLAG_STRING, 9);
243
sprintf (upsSerial, "B5%c.%c", buf[4], buf[6]);
244
addinfo (INFO_SERIAL, upsSerial, FLAG_STRING, 5);
255
static int polling_ok (char *buf, unsigned buflen)
257
if ((buflen==NUM_POLLING_BYTES) && (buf[0]==91) &&
258
(buf[NUM_POLLING_BYTES-1]==93) && (buf[1]==1))
268
/* wait for buflen bytes from upsfd and store in buf */
269
static int read_raw_data (int upsfd, char *buf, int buflen)
276
sa.sa_handler = timeout;
277
sigemptyset (&sigmask);
278
sa.sa_mask = sigmask;
280
sigaction (SIGALRM, &sa, NULL);
284
for (counter = 0; counter < buflen; counter++)
287
ret = (read (upsfd, buf + counter, 1));
290
signal (SIGALRM, SIG_IGN);
301
static void setuphandlers(void)
303
upsh.instcmd = instcmd;
306
static void updateinfo (unsigned int line_voltage, char *raw_data)
309
unsigned char loadpct;
311
myups.acfreq = 61440.0 / ((255 - (unsigned char)raw_data[ACFREQ_H]) * 256 + (256 - (unsigned char)raw_data[ACFREQ_L]));
312
setinfo(INFO_ACFREQ, "%04.1f", myups.acfreq);
314
myups.utility = 1.84 * (unsigned char)raw_data[UTILITY];
315
setinfo(INFO_UTILITY, "%05.1f", myups.utility);
317
myups.battvolt = (1.0 * (unsigned char)raw_data[BATTVOLT]) / 16.82;
318
if (myups.upsmodel > 100)
319
myups.battvolt *= 2.0;
320
setinfo(INFO_BATTVOLT, "%05.2f", myups.battvolt);
323
if (myups.upsmodel > 100)
326
loadpct = (unsigned char)raw_data[LOADPCT];
327
if (loadpct < LOAD_T0)
331
else if ((loadpct >= LOAD_T0) && (loadpct < LOAD_T1))
336
else if ((loadpct >= LOAD_T1) && (loadpct < LOAD_T2))
341
else if ((loadpct >= LOAD_T2) && (loadpct < LOAD_T3))
346
else if ((loadpct >= LOAD_T3) && (loadpct < LOAD_T4))
349
myups.loadpct += 100;
351
else if (loadpct >= LOAD_T4)
354
myups.loadpct += 120;
356
setinfo(INFO_LOADPCT, "%s", val);
361
myups.upstemp = 27.0;
363
setinfo(INFO_UPSTEMP, "%s", val);
366
myups.upshour = (unsigned char)raw_data[UPS_HOUR];
367
myups.upsmin = (unsigned char)raw_data[UPS_MIN];
368
myups.upssec = (unsigned char)raw_data[UPS_SEC];
369
myups.houron = (unsigned char)raw_data[UPS_HOUR_ON];
370
myups.minon = (unsigned char)raw_data[UPS_MIN_ON];
371
myups.houroff = (unsigned char)raw_data[UPS_HOUR_OFF];
372
myups.sddelay = (unsigned char)raw_data[SD_DELAY];
376
if (!(raw_data[STATUS] & MAINS_FAILURE))
379
myups.battruntime = 0;
380
if (!is_set(myups.status, ST_ONLINE))
382
set_flag (&myups.status, ST_ONLINE);
383
clear_flag (&myups.status, ST_ONBATT);
389
if (!is_set(myups.status, ST_ONBATT))
391
set_flag (&myups.status, ST_ONBATT);
392
clear_flag (&myups.status, ST_ONLINE);
394
if (myups.maxbattruntime > 0) {
395
if (++myups.battruntime > myups.maxbattruntime) {
397
set_flag (&myups.status, ST_LOWBATT);
403
if (raw_data[STATUS] & LOW_BAT)
406
if (!is_set(myups.status, ST_LOWBATT))
408
set_flag (&myups.status, ST_LOWBATT);
411
if (raw_data[STATUS] & END_BAT)
414
if (raw_data[STATUS] & HIGH_TEMP)
417
if (raw_data[STATUS] & DANGER_TEMP)
420
*(val + strlen(val)) = 0;
421
setinfo(INFO_STATUS, "%s", val);
427
int main (int argc, char **argv)
429
char *portname, *prog,
430
*ups_model = 0, *ups_serial_num = 0,
432
char raw_data[NUM_OF_BYTES_FROM_UPS];
433
int i, shutdown_now = 0;
434
unsigned int numpollko = 0;
435
unsigned int pollcount = 0;
437
printf ("Network UPS Tools - MicroDowell UPS driver 0.01 (%s)\n",
439
openlog ("MicroDowell", LOG_CONS | LOG_PID, LOG_FACILITY);
446
while ((i = getopt(argc, argv, "+hkd:l:b:")) != EOF) {
449
sddelay = atoi (optarg);
455
line_voltage = atoi(optarg);
458
myups.maxbattruntime = atoi(optarg);
459
if (myups.maxbattruntime > 0)
460
myups.maxbattruntime /= 2;
477
for (i = strlen(argv[0]); i >= 0; i--)
478
if (argv[0][i] == '/') {
479
portname = &argv[0][i+1];
483
if (portname == NULL)
484
fatalx("Unable to abbreviate %s", argv[0]);
486
open_serial (argv[0], B1200);
488
snprintf (statefn, sizeof(statefn), "%s/microdowell-%s", STATEPATH,
491
initinfo(ups_ident, ups_model, ups_serial_num);
494
forceshutdown (sddelay);
496
createmsgq(); /* try to create IPC message queue */
502
if (setupstime () < 0)
503
printf ("Unable to set timer \n");
505
if (upssendchar (SEND_DATA) != 1) {
506
upslogx(LOG_NOTICE, "%s writing error", argv[0]);
509
else if (read_raw_data(upsfd, raw_data,NUM_POLLING_BYTES) == NUM_POLLING_BYTES) {
510
if (polling_ok (raw_data, NUM_POLLING_BYTES) == 1) {
511
if (is_set(myups.status, ST_BADCOM)) {
512
clear_flag (&myups.status, ST_BADCOM);
513
printf ("UPS communication established \n");
515
updateinfo (line_voltage, raw_data);
525
if (numpollko > NUM_POLLS_KO) {
527
if (!is_set(myups.status, ST_BADCOM)) {
529
set_flag (&myups.status, ST_BADCOM);
530
printf ("UPS communication lost \n");
533
if (++pollcount >= 1800) {
534
if (setupstime () < 0)
535
printf ("Unable to set timer \n");
539
/* wait up to 2 seconds for a message from the upsd */
541
upslogx(LOG_INFO, "Received a message from upsd");