99
static int do_status(void)
110
static int get_belkin_reply(char *buf)
101
char temp[SMALLBUF], st[SMALLBUF];
104
send_belkin_command(STATUS,STAT_STATUS,"");
105
res = get_belkin_reply(temp);
118
/* pull first 7 bytes to get data length - like ~00D004 */
119
ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 2, 0);
122
ser_comm_fail("Initial read returned %d bytes", ret);
127
cnt = strtol(tmp + 4, NULL, 10);
128
upsdebugx(3, "Received: %s", tmp);
130
if (cnt == 0) { /* possible to have ~00R000, return empty response */
113
get_belkin_field(temp, st, sizeof(st), 6);
117
} else { /* (OFF) and (OB | OL) are mutually exclusive */
119
get_belkin_field(temp, st, sizeof(st), 2);
123
send_belkin_command(STATUS,STAT_BATTERY,"");
124
res = get_belkin_reply(temp);
131
get_belkin_field(temp, st, sizeof(st), 10);
133
get_belkin_field(temp, st, sizeof(st), 2);
135
if (*st == '1' || res < LOW_BAT)
136
status_set("LB"); /* low battery */
139
status_set("OL"); /* on line */
135
if ((cnt < 0) || (cnt > 255)) {
139
/* give it time to respond to us */
142
ret = ser_get_buf_len(upsfd, (unsigned char *)buf, cnt, 2, 0);
145
upsdebugx(3, "Received: %s", buf);
148
ser_comm_fail("Second read returned %d bytes, expected %ld", ret, cnt);
148
157
static int do_broken_rat(char *buf)
155
ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 3, 0);
163
if ((cnt < 1) || (cnt > 255))
165
/* pull first 7 bytes to get data length - like ~00D004 */
166
ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 2, 0);
169
ser_comm_fail("Initial read returned %d bytes", ret);
174
cnt = strtol(tmp + 4, NULL, 10);
175
upsdebugx(3, "Received: %s", tmp);
177
if (cnt == 0) { /* possible to have ~00R000, return empty response */
182
if ((cnt < 0) || (cnt > 255)) {
186
/* give it time to respond to us */
166
187
usleep(5000 * cnt);
168
189
/* firmware 001 only sends 50 bytes instead of the proper 53 */
172
ret = ser_get_buf_len(upsfd, (unsigned char *)buf, 50, cnt, 0);
194
ret = ser_get_buf_len(upsfd, (unsigned char *)buf, cnt, 2, 0);
197
upsdebugx(3, "Received: %s", buf);
200
ser_comm_fail("Second read returned %d bytes, expected %ld", ret, cnt);
178
static int init_ups_data(void)
182
char temp[SMALLBUF], st[SMALLBUF];
184
send_belkin_command(STATUS, MODEL, "");
185
res = get_belkin_reply(temp);
189
dstate_setinfo("ups.model", "%s", temp);
191
send_belkin_command(STATUS, VERSION_CMD, "");
192
res = get_belkin_reply(temp);
196
dstate_setinfo("ups.firmware", "%s", temp);
198
/* deal with stupid firmware that breaks RAT */
200
send_belkin_command(STATUS, RATING, "");
202
if (!strcmp(temp, "001"))
203
res = do_broken_rat(temp);
205
res = get_belkin_reply(temp);
208
get_belkin_field(temp, st, sizeof(st), 8);
209
low = atof(st) / 0.88;
211
get_belkin_field(temp, st, sizeof(st), 9);
212
high = atof(st) * 0.88;
214
dstate_setinfo("input.transfer.low", "%03.1f", low);
215
dstate_setinfo("input.transfer.high", "%03.1f", high);
220
dstate_addcmd("load.off");
221
dstate_addcmd("load.on");
226
209
/* normal idle loop - keep up with the current state of the UPS */
227
210
void upsdrv_updateinfo(void)
212
static int retry = 0;
231
214
char temp[SMALLBUF], st[SMALLBUF];
216
send_belkin_command(STATUS, STAT_STATUS, "");
217
res = get_belkin_reply(temp);
219
if (retry < MAXTRIES) {
220
upsdebugx(1, "Communications with UPS lost: status read failed!");
222
} else { /* too many retries */
223
upslogx(LOG_WARNING, "Communications with UPS lost: status read failed!");
229
if (retry) { /* previous attempt had failed */
230
upslogx(LOG_WARNING, "Communications with UPS re-established");
235
upsdebugx(1, "Ignoring empty return value after status query");
241
get_belkin_field(temp, st, sizeof(st), 6);
246
get_belkin_field(temp, st, sizeof(st), 2);
248
status_set("OB"); /* on battery */
250
status_set("OL"); /* on line */
253
get_belkin_field(temp, st, sizeof(st), 16);
254
dstate_setinfo("ups.beeper.status", "%s", (*st == '0' ? "disabled" : "enabled"));
256
send_belkin_command(STATUS, STAT_BATTERY, "");
257
res = get_belkin_reply(temp);
259
/* report the compiled in battery charge where the driver assumes the battery is low */
260
dstate_setinfo("battery.charge.low", "%d", LOW_BAT);
262
get_belkin_field(temp, st, sizeof(st), 10);
264
get_belkin_field(temp, st, sizeof(st), 2);
266
if (*st == '1' || res < LOW_BAT) {
267
status_set("LB"); /* low battery */
270
get_belkin_field(temp, st, sizeof(st), 10);
271
dstate_setinfo("battery.charge", "%.0f", strtod(st, NULL));
273
get_belkin_field(temp, st, sizeof(st), 9);
274
dstate_setinfo("battery.temperature", "%.0f", strtod(st, NULL));
276
get_belkin_field(temp, st, sizeof(st), 7);
277
dstate_setinfo("battery.voltage", "%.1f", strtod(st, NULL) / 10);
279
get_belkin_field(temp, st, sizeof(st), 9);
280
dstate_setinfo("ups.temperature", "%.0f", strtod(st, NULL));
236
283
send_belkin_command(STATUS, STAT_INPUT, "");
237
284
res = get_belkin_reply(temp);
241
get_belkin_field(temp, st, sizeof(st), 3);
243
dstate_setinfo("input.voltage", "%05.1f", val);
245
get_belkin_field(temp, st, sizeof(st), 2);
247
dstate_setinfo("input.frequency", "%.1f", val);
249
send_belkin_command(STATUS,STAT_BATTERY, "");
250
res = get_belkin_reply(temp);
254
get_belkin_field(temp, st, sizeof(st), 10);
256
dstate_setinfo("battery.charge", "%03.0f", val);
258
get_belkin_field(temp, st, sizeof(st), 9);
260
dstate_setinfo("battery.temperature", "%03.0f", val);
262
get_belkin_field(temp, st, sizeof(st), 7);
264
dstate_setinfo("battery.voltage", "%4.1f", val);
266
get_belkin_field(temp, st, sizeof(st), 9);
268
dstate_setinfo("ups.temperature", "%03.0f", val);
286
get_belkin_field(temp, st, sizeof(st), 3);
287
dstate_setinfo("input.voltage", "%.1f", strtod(st, NULL) / 10);
289
get_belkin_field(temp, st, sizeof(st), 2);
290
dstate_setinfo("input.frequency", "%.1f", strtod(st, NULL) / 10);
270
293
send_belkin_command(STATUS, STAT_OUTPUT, "");
271
294
res = get_belkin_reply(temp);
275
get_belkin_field(temp, st, sizeof(st), 2);
277
dstate_setinfo("output.frequency", "%.1f", val);
279
get_belkin_field(temp, st, sizeof(st), 4);
281
dstate_setinfo("output.voltage", "%05.1f", val);
283
get_belkin_field(temp, st, sizeof(st), 7);
285
dstate_setinfo("ups.load", "%03.0f", val);
288
static int get_belkin_reply(char *buf)
295
/* pull first 7 bytes to get data length - like ~00S004 */
296
ret = ser_get_buf_len(upsfd, (unsigned char *)tmp, 7, 3, 0);
299
ser_comm_fail("Initial read returned %d bytes", ret);
306
if ((cnt < 1) || (cnt > 255))
309
/* give it time to respond to us */
312
ret = ser_get_buf_len(upsfd, (unsigned char *)buf, cnt, 3, 0);
317
ser_comm_fail("Second read returned %d bytes, expected %d",
296
get_belkin_field(temp, st, sizeof(st), 2);
297
dstate_setinfo("output.frequency", "%.1f", strtod(st, NULL) / 10);
299
get_belkin_field(temp, st, sizeof(st), 4);
300
dstate_setinfo("output.voltage", "%.1f", strtod(st, NULL) / 10);
302
get_belkin_field(temp, st, sizeof(st), 7);
303
dstate_setinfo("ups.load", "%.0f", strtod(st, NULL));
306
send_belkin_command(STATUS, TEST_RESULT, "");
307
res = get_belkin_reply(temp);
309
get_belkin_field(temp, st, sizeof(st), 1);
313
dstate_setinfo("ups.test.result", "%s", "No test performed");
317
dstate_setinfo("ups.test.result", "%s", "Passed");
321
dstate_setinfo("ups.test.result", "%s", "In progress");
326
dstate_setinfo("ups.test.result", "%s", "10s test failed");
330
dstate_setinfo("ups.test.result", "%s", "deep test failed");
334
dstate_setinfo("ups.test.result", "%s", "Aborted");
338
upsdebugx(3, "Unhandled test status '%c'", *st);
327
348
/* power down the attached load immediately */