4 * CI -> OID mapping for SNMP Lite UPS driver
8 * Copyright (C) 2009 Adam Kropelin
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU General
12 * Public License as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public
20 * License along with this program; if not, write to the Free
21 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26 #include "snmplite-common.h"
32 static struct CiOidMap CiOidMap
[] =
34 // CI OID type dynamic?
35 {CI_UPSMODEL
, upsBasicIdentModel
, OCTETSTRING
, false},
36 {CI_SERNO
, upsAdvIdentSerialNumber
, OCTETSTRING
, false},
37 {CI_IDEN
, upsBasicIdentName
, OCTETSTRING
, false},
38 {CI_REVNO
, upsAdvIdentFirmwareRevision
, OCTETSTRING
, false},
39 {CI_MANDAT
, upsAdvIdentDateOfManufacture
, OCTETSTRING
, false},
40 {CI_BATTDAT
, upsBasicBatteryLastReplaceDate
, OCTETSTRING
, false},
41 {CI_NOMBATTV
, upsAdvBatteryNominalVoltage
, INTEGER
, false},
42 {CI_NOMOUTV
, upsAdvConfigRatedOutputVoltage
, INTEGER
, false},
43 {CI_LTRANS
, upsAdvConfigLowTransferVolt
, INTEGER
, false},
44 {CI_HTRANS
, upsAdvConfigHighTransferVolt
, INTEGER
, false},
45 {CI_DWAKE
, upsAdvConfigReturnDelay
, TIMETICKS
, false},
46 {CI_AlarmTimer
, upsAdvConfigAlarmTimer
, TIMETICKS
, false}, // Must be before CI_DALARM
47 {CI_DALARM
, upsAdvConfigAlarm
, INTEGER
, false},
48 {CI_DLBATT
, upsAdvConfigLowBatteryRunTime
, TIMETICKS
, false},
49 {CI_DSHUTD
, upsAdvConfigShutoffDelay
, TIMETICKS
, false},
50 {CI_RETPCT
, upsAdvConfigMinReturnCapacity
, INTEGER
, false},
51 {CI_SENS
, upsAdvConfigSensitivity
, INTEGER
, false},
52 {CI_EXTBATTS
, upsAdvBatteryNumOfBattPacks
, INTEGER
, false},
53 {CI_STESTI
, upsAdvTestDiagnosticSchedule
, INTEGER
, false},
54 {CI_VLINE
, upsAdvInputLineVoltage
, GAUGE
, true },
55 {CI_VOUT
, upsAdvOutputVoltage
, GAUGE
, true },
56 {CI_VBATT
, upsAdvBatteryActualVoltage
, INTEGER
, true },
57 {CI_FREQ
, upsAdvInputFrequency
, GAUGE
, true },
58 {CI_LOAD
, upsAdvOutputLoad
, GAUGE
, true },
59 {CI_ITEMP
, upsAdvBatteryTemperature
, GAUGE
, true },
60 {CI_ATEMP
, mUpsEnvironAmbientTemperature
, GAUGE
, true },
61 {CI_HUMID
, mUpsEnvironRelativeHumidity
, GAUGE
, true },
62 {CI_ST_STAT
, upsAdvTestDiagnosticsResults
, INTEGER
, true },
63 {CI_BATTLEV
, upsAdvBatteryCapacity
, GAUGE
, true },
64 {CI_RUNTIM
, upsAdvBatteryRunTimeRemaining
, TIMETICKS
, true },
65 {CI_WHY_BATT
, upsAdvInputLineFailCause
, INTEGER
, true },
66 {CI_BADBATTS
, upsAdvBatteryNumOfBadBattPacks
, INTEGER
, true },
67 {CI_VMIN
, upsAdvInputMinLineVoltage
, GAUGE
, true },
68 {CI_VMAX
, upsAdvInputMaxLineVoltage
, GAUGE
, true },
70 // These 5 collectively are used to obtain the data for CI_STATUS.
71 // All bits are available in upsBasicStateOutputState at once but
72 // the old AP960x cards do not appear to support that OID, so we use
73 // it only for the overload flag which is not available elsewhere.
74 {CI_STATUS
, upsBasicOutputStatus
, INTEGER
, true },
75 {CI_NeedReplacement
, upsAdvBatteryReplaceIndicator
, INTEGER
, true },
76 {CI_LowBattery
, upsBasicBatteryStatus
, INTEGER
, true },
77 {CI_Calibration
, upsAdvTestCalibrationResults
, INTEGER
, true },
78 {CI_Overload
, upsBasicStateOutputState
, OCTETSTRING
, true },
80 {-1, NULL
, false} /* END OF TABLE */
83 #define TIMETICKS_TO_SECS 100
84 #define SECS_TO_MINS 60
86 static void apc_update_ci(UPSINFO
*ups
, int ci
, Snmp::Variable
&data
)
88 static unsigned int alarmtimer
= 0;
93 Dmsg1(80, "Got CI_VLINE: %d\n", data
.u32
);
94 ups
->LineVoltage
= data
.u32
;
98 Dmsg1(80, "Got CI_VOUT: %d\n", data
.u32
);
99 ups
->OutputVoltage
= data
.u32
;
103 Dmsg1(80, "Got CI_VBATT: %d\n", data
.u32
);
104 ups
->BattVoltage
= data
.u32
;
108 Dmsg1(80, "Got CI_FREQ: %d\n", data
.u32
);
109 ups
->LineFreq
= data
.u32
;
113 Dmsg1(80, "Got CI_LOAD: %d\n", data
.u32
);
114 ups
->UPSLoad
= data
.u32
;
118 Dmsg1(80, "Got CI_ITEMP: %d\n", data
.u32
);
119 ups
->UPSTemp
= data
.u32
;
123 Dmsg1(80, "Got CI_ATEMP: %d\n", data
.u32
);
124 ups
->ambtemp
= data
.u32
;
128 Dmsg1(80, "Got CI_HUMID: %d\n", data
.u32
);
129 ups
->humidity
= data
.u32
;
133 Dmsg1(80, "Got CI_NOMBATTV: %d\n", data
.u32
);
134 ups
->nombattv
= data
.u32
;
138 Dmsg1(80, "Got CI_NOMOUTV: %d\n", data
.u32
);
139 ups
->NomOutputVoltage
= data
.u32
;
143 Dmsg1(80, "Got CI_NOMINV: %d\n", data
.u32
);
144 ups
->NomInputVoltage
= data
.u32
;
148 Dmsg1(80, "Got CI_NOMPOWER: %d\n", data
.u32
);
149 ups
->NomPower
= data
.u32
;
153 Dmsg1(80, "Got CI_LTRANS: %d\n", data
.u32
);
154 ups
->lotrans
= data
.u32
;
158 Dmsg1(80, "Got CI_HTRANS: %d\n", data
.u32
);
159 ups
->hitrans
= data
.u32
;
163 Dmsg1(80, "Got CI_DWAKE: %d\n", data
.u32
);
164 ups
->dwake
= data
.u32
;
168 Dmsg1(80, "Got CI_ST_STAT: %d\n", data
.u32
);
172 ups
->testresult
= TEST_PASSED
;
175 case 3: /* Invalid test */
176 ups
->testresult
= TEST_FAILED
;
178 case 4: /* Test in progress */
179 ups
->testresult
= TEST_INPROGRESS
;
182 ups
->testresult
= TEST_UNKNOWN
;
188 Dmsg1(80, "Got CI_AlarmTimer: %d\n", data
.u32
);
189 // Remember alarm timer setting; we will use it for CI_DALARM
190 alarmtimer
= data
.u32
;
194 Dmsg1(80, "Got CI_DALARM: %d\n", data
.u32
);
197 case 1: // Timed (uses CI_AlarmTimer)
198 if (ups
->UPS_Cap
[CI_AlarmTimer
] && alarmtimer
< 30)
199 astrncpy(ups
->beepstate
, "0", sizeof(ups
->beepstate
)); // 5 secs
201 astrncpy(ups
->beepstate
, "T", sizeof(ups
->beepstate
)); // 30 secs
204 astrncpy(ups
->beepstate
, "L", sizeof(ups
->beepstate
));
207 astrncpy(ups
->beepstate
, "N", sizeof(ups
->beepstate
));
210 astrncpy(ups
->beepstate
, "T", sizeof(ups
->beepstate
));
216 Dmsg1(80, "Got CI_UPSMODEL: %s\n", data
.str
.str());
217 astrncpy(ups
->upsmodel
, data
.str
, sizeof(ups
->upsmodel
));
221 Dmsg1(80, "Got CI_SERNO: %s\n", data
.str
.str());
222 astrncpy(ups
->serial
, data
.str
, sizeof(ups
->serial
));
226 Dmsg1(80, "Got CI_MANDAT: %s\n", data
.str
.str());
227 astrncpy(ups
->birth
, data
.str
, sizeof(ups
->birth
));
231 Dmsg1(80, "Got CI_BATTLEV: %d\n", data
.u32
);
232 ups
->BattChg
= data
.u32
;
236 Dmsg1(80, "Got CI_RUNTIM: %d\n", data
.u32
);
237 ups
->TimeLeft
= data
.u32
/ TIMETICKS_TO_SECS
/ SECS_TO_MINS
;
241 Dmsg1(80, "Got CI_BATTDAT: %s\n", data
.str
.str());
242 astrncpy(ups
->battdat
, data
.str
, sizeof(ups
->battdat
));
246 Dmsg1(80, "Got CI_IDEN: %s\n", data
.str
.str());
247 astrncpy(ups
->upsname
, data
.str
, sizeof(ups
->upsname
));
251 Dmsg1(80, "Got CI_STATUS: %d\n", data
.u32
);
252 /* Clear the following flags: only one status will be TRUE */
272 case 1: /* unknown */
273 case 5: /* timed sleeping */
274 case 6: /* software bypass */
275 case 7: /* UPS off */
276 case 8: /* UPS rebooting */
277 case 9: /* switched bypass */
278 case 10: /* hardware failure bypass */
279 case 11: /* sleeping until power returns */
280 default: /* unknown */
285 case CI_NeedReplacement
:
286 Dmsg1(80, "Got CI_NeedReplacement: %d\n", data
.u32
);
288 ups
->set_replacebatt();
290 ups
->clear_replacebatt();
294 Dmsg1(80, "Got CI_LowBattery: %d\n", data
.u32
);
298 ups
->clear_battlow();
302 Dmsg1(80, "Got CI_Calibration: %d\n", data
.u32
);
304 ups
->set_calibration();
306 ups
->clear_calibration();
310 Dmsg1(80, "Got CI_Overload: %c\n", data
.str
[8]);
311 if (data
.str
[8] == '1')
314 ups
->clear_overload();
318 Dmsg1(80, "Got CI_DSHUTD: %d\n", data
.u32
);
319 ups
->dshutd
= data
.u32
/ TIMETICKS_TO_SECS
;
323 Dmsg1(80, "Got CI_RETPCT: %d\n", data
.u32
);
324 ups
->rtnpct
= data
.u32
;
331 ups
->lastxfer
= XFER_NONE
;
333 case 2: /* High line voltage */
334 ups
->lastxfer
= XFER_OVERVOLT
;
336 case 3: /* Brownout */
337 case 4: /* Blackout */
338 ups
->lastxfer
= XFER_UNDERVOLT
;
340 case 5: /* Small sag */
341 case 6: /* Deep sag */
342 case 7: /* Small spike */
343 case 8: /* Deep spike */
344 ups
->lastxfer
= XFER_NOTCHSPIKE
;
347 ups
->lastxfer
= XFER_SELFTEST
;
350 ups
->lastxfer
= XFER_RIPPLE
;
353 ups
->lastxfer
= XFER_UNKNOWN
;
359 Dmsg1(80, "Got CI_SENS: %d\n", data
.u32
);
363 astrncpy(ups
->sensitivity
, "Auto", sizeof(ups
->sensitivity
));
366 astrncpy(ups
->sensitivity
, "Low", sizeof(ups
->sensitivity
));
369 astrncpy(ups
->sensitivity
, "Medium", sizeof(ups
->sensitivity
));
372 astrncpy(ups
->sensitivity
, "High", sizeof(ups
->sensitivity
));
375 astrncpy(ups
->sensitivity
, "Unknown", sizeof(ups
->sensitivity
));
381 Dmsg1(80, "Got CI_REVNO: %s\n", data
.str
.str());
382 astrncpy(ups
->firmrev
, data
.str
, sizeof(ups
->firmrev
));
386 Dmsg1(80, "Got CI_EXTBATTS: %d\n", data
.u32
);
387 ups
->extbatts
= data
.u32
;
391 Dmsg1(80, "Got CI_BADBATTS: %d\n", data
.u32
);
392 ups
->badbatts
= data
.u32
;
396 Dmsg1(80, "Got CI_DLBATT: %d\n", data
.u32
);
397 ups
->dlowbatt
= data
.u32
/ TIMETICKS_TO_SECS
/ SECS_TO_MINS
;
401 Dmsg1(80, "Got CI_STESTI: %d\n", data
.u32
);
404 astrncpy(ups
->selftest
, "336", sizeof(ups
->selftest
));
407 astrncpy(ups
->selftest
, "168", sizeof(ups
->selftest
));
410 astrncpy(ups
->selftest
, "ON", sizeof(ups
->selftest
));
415 astrncpy(ups
->selftest
, "OFF", sizeof(ups
->selftest
));
421 Dmsg1(80, "Got CI_VMIN: %d\n", data
.u32
);
422 ups
->LineMin
= data
.u32
;
426 Dmsg1(80, "Got CI_VMAX: %d\n", data
.u32
);
427 ups
->LineMax
= data
.u32
;
432 static int apc_killpower(UPSINFO
*ups
)
434 struct snmplite_ups_internal_data
*sid
=
435 (struct snmplite_ups_internal_data
*)ups
->driver_internal_data
;
437 Snmp::Variable var
= { Asn::INTEGER
, 2 };
438 return sid
->snmp
->Set(upsBasicControlConserveBattery
, &var
);
441 static int apc_shutdown(UPSINFO
*ups
)
443 struct snmplite_ups_internal_data
*sid
=
444 (struct snmplite_ups_internal_data
*)ups
->driver_internal_data
;
446 Snmp::Variable var
= { Asn::INTEGER
, 2 };
447 return sid
->snmp
->Set(upsAdvControlUpsOff
, &var
);
450 // Export strategy to snmplite.cpp
451 struct MibStrategy ApcMibStrategy
=