our
$VERSION
=
'0.02'
;
sub
new {
my
(
$class
,
$args
) =
@_
;
my
$self
= {
hostname
=> (
defined
(
$args
->{
'hostname'
}) ?
$args
->{
'hostname'
} :
undef
),
ip
=>
undef
,
class
=>
$class
,
error
=> 0,
errorstr
=>
''
,
community
=> (
defined
(
$args
->{
'community'
}) ?
$args
->{
'community'
} :
'public'
),
lastquery
=>
undef
,
};
$self
=
bless
(
$self
);
$self
->_check();
return
$self
;
}
sub
error {
my
$self
=
shift
;
return
1
if
$self
->{
'error'
};
return
0;
}
sub
errstr {
my
$self
=
shift
;
return
undef
unless
$self
->{
'error'
};
my
$err
=
"unknown error"
;
$err
=
$self
->{
'errorstr'
}
if
$self
->{
'errorstr'
};
return
$err
;
}
sub
_check {
my
$self
=
shift
;
return
$self
->_rerror(
"No UPS hostname specified."
)
unless
$self
->{
'hostname'
};
$self
->_resolve
unless
$self
->error;
}
sub
_resolve {
my
$self
=
shift
;
my
$tmp
=
undef
;
$tmp
= inet_aton(
$self
->{
'hostname'
});
if
(
$tmp
) {
$self
->{
'ip'
} = inet_ntoa(
$tmp
);
}
$self
->_rerror(
"Can't resolve: "
.
$self
->{'hostname'})
unless
$self
->{
'ip'
};
}
sub
_ping {
my
$self
=
shift
;
my
$p
= Net::Ping->new(
"icmp"
);
unless
(
$p
->ping(
$self
->{
'ip'
},1)) {
$self
->_rerror(
$self
->{
'hostname'
} .
" ("
.
$self
->{
'ip'
} .
") not reachable."
);
}
}
sub
query {
my
$self
=
shift
;
$self
->_qups();
return
if
$self
->error();
$self
->{
'lastquery'
} = DateTime->now();
$self
->_parseresult();
}
sub
_rerror {
my
$self
=
shift
;
my
$err
=
shift
;
$self
->{
'error'
} = 1;
$self
->{
'errorstr'
} =
$err
;
return
$self
;
}
sub
_decodetable {
my
$table
= {
'upsBasicOutputStatus'
=> {
1
=>
'unknown'
,
2
=>
'onLine'
,
3
=>
'onBattery'
,
4
=>
'onSmartBoost'
,
5
=>
'timedSleeping'
,
6
=>
'softwareBypass'
,
7
=>
'off'
,
8
=>
'rebooting'
,
9
=>
'swtichedBypass'
,
10
=>
'hardwareFailureBypass'
,
11
=>
'sleepingUntilPowerReturn'
,
12
=>
'onSmartTrim'
,
},
'upsAdvInputLineFailCause'
=> {
1
=>
'noTransfer'
,
2
=>
'highLineVoltage'
,
3
=>
'brownout'
,
4
=>
'blackout'
,
5
=>
'smallMomentarySag'
,
6
=>
'deepMomentarySag'
,
7
=>
'smallMomentarySpike'
,
8
=>
'largeMomentarySpike'
,
9
=>
'selfTest'
,
10
=>
'rateOfVoltageChange'
,
},
'upsAdvBatteryReplaceIndicator'
=> {
1
=>
'noBatteryNeedsReplacing'
,
2
=>
'batteryNeedsReplacing'
,
},
'upsBasicBatteryStatus'
=> {
1
=>
'unknown'
,
2
=>
'batteryNormal'
,
3
=>
'batteryLow'
,
},
};
return
$table
;
}
sub
_parseresult {
my
$self
=
shift
;
my
$t
= _decodetable();
my
@oids
=
keys
(%{
$t
});
my
%h
= %{
$self
->{
'rawstatus'
}};
my
$stat
= \
%h
;
foreach
(
@oids
) {
if
(
exists
(
$stat
->{
$_
})) {
$stat
->{
$_
} =
$t
->{
$_
}{
$stat
->{
$_
}};
}
}
my
@doids
= (
'upsAdvIdentDateOfManufacture'
,
'upsBasicBatteryLastReplaceDate'
,
);
foreach
(
@doids
) {
$stat
->{
$_
} =
_dconvert_mmddyy_to_dt(
$self
->{
'rawstatus'
}{
$_
});
}
$self
->{
'status'
} =
$stat
;
}
sub
_dconvert_mmddyy_to_dt {
my
$mmddyy
=
shift
;
my
@p
=
split
(/\//,
$mmddyy
);
$p
[2] += 1900
if
$p
[2] > 50;
$p
[2] += 2000
if
$p
[2] < 50;
my
$dt
= DateTime->new(
year
=>
$p
[2],
month
=>
$p
[0],
day
=>
$p
[1],
);
return
$dt
;
}
sub
_qups {
my
$self
=
shift
;
return
if
$self
->error();
'pnetmib/mib/381/powernet381.mib'
;
my
$mib
=
'/usr/share/snmp/mibs/powernet381.mib'
;
return
$self
->_rerror(
"Can't read MIB: '$mib'. "
.
"Maybe you need to download it from '$miburl'?"
)
unless
-r
$mib
;
$ENV
{
'MIBS'
} =
$mib
;
my
$sess
= new SNMP::Session (
DestHost
=>
$self
->{
'ip'
},
Community
=>
$self
->{
'community'
},
Version
=> 1,
Timeout
=> 500000,
Retries
=> 1,
);
return
$self
->_rerror(
"Unable to SNMP."
)
unless
$sess
;
my
@attr
= (
'upsAdvBatteryNominalVoltage'
,
'upsAdvBatteryActualVoltage'
,
'upsAdvBatteryCurrent'
,
'upsAdvTotalDCCurrent'
,
'upsBasicIdentModel'
,
'upsAdvIdentSerialNumber'
,
'upsAdvBatteryCapacity'
,
'upsAdvBatteryTemperature'
,
'upsBasicInputPhase'
,
'upsBasicOutputPhase'
,
'upsAdvOutputLoad'
,
'upsAdvOutputVoltage'
,
'upsAdvOutputFrequency'
,
'upsBasicOutputStatus'
,
'upsAdvBatteryRunTimeRemaining'
,
'upsAdvInputMaxLineVoltage'
,
'upsAdvInputMinLineVoltage'
,
'upsAdvInputLineVoltage'
,
'upsAdvInputFrequency'
,
'upsAdvInputLineFailCause'
,
'upsBasicIdentName'
,
'upsAdvIdentFirmwareRevision'
,
'upsAdvIdentDateOfManufacture'
,
'upsAdvBatteryReplaceIndicator'
,
'upsBasicBatteryLastReplaceDate'
,
'upsBasicBatteryTimeOnBattery'
,
'upsBasicBatteryStatus'
,
);
my
@arg
;
foreach
(
@attr
) {
push
(
@arg
,[
$_
]);
}
my
$vl
= new SNMP::VarList(
@arg
);
my
@info
=
$sess
->getnext(
$vl
);
return
$self
->_rerror(
"Unable to fetch UPS parameters."
)
unless
@info
;
my
$x
= 0;
my
$h
= { };
foreach
(
@attr
) {
$h
->{
$attr
[
$x
]} =
$info
[
$x
];
$x
++;
}
$self
->{
'rawstatus'
} =
$h
;
}
sub
hostname {
my
$self
=
shift
;
return
undef
if
$self
->error;
return
$self
->{
'hostname'
};
}
sub
onbattery {
my
$self
=
shift
;
$self
->query
unless
$self
->{
'lastquery'
};
return
undef
if
$self
->error;
return
undef
if
$self
->{
'status'
}{
'upsBasicOutputStatus'
} eq
'unknown'
;
return
1
if
$self
->{
'status'
}{
'upsBasicOutputStatus'
} eq
'onBattery'
;
return
1
if
$self
->{
'status'
}{
'upsBasicOutputStatus'
} eq
'onSmartBoost'
;
return
0;
}
sub
status {
my
$self
=
shift
;
$self
->query
unless
$self
->{
'lastquery'
};
return
undef
if
$self
->error;
my
%h
= %{
$self
->{
'status'
}};
return
\
%h
;
}
sub
needsnewbatt {
my
$self
=
shift
;
$self
->query
unless
$self
->{
'lastquery'
};
return
undef
if
$self
->error;
if
(
$self
->{
'status'
}{
'upsAdvBatteryReplaceIndicator'
}
eq
'batteryNeedsReplacing'
) {
return
1;
}
elsif
(
$self
->{
'status'
}{
'upsAdvBatteryReplaceIndicator'
}
eq
'noBatteryNeedsReplacing'
) {
return
0;
}
else
{
return
undef
;
}
}
sub
runtime {
my
$self
=
shift
;
$self
->query
unless
$self
->{
'lastquery'
};
return
undef
if
$self
->error;
my
$s
=
$self
->{
'status'
}{
'upsAdvBatteryRunTimeRemaining'
}/100;
$s
=
int
(
$s
);
return
$s
;
}
sub
charge {
my
$self
=
shift
;
$self
->query
unless
$self
->{
'lastquery'
};
return
undef
if
$self
->error;
my
$p
=
$self
->{
'status'
}{
'upsAdvBatteryCapacity'
}/100;
return
$p
;
}
sub
model {
my
$self
=
shift
;
$self
->query
unless
$self
->{
'lastquery'
};
return
undef
if
$self
->error;
return
$self
->{
'status'
}{
'upsBasicIdentModel'
};
}
sub
serial {
my
$self
=
shift
;
$self
->query
unless
$self
->{
'lastquery'
};
return
undef
if
$self
->error;
return
$self
->{
'status'
}{
'upsAdvIdentSerialNumber'
};
}
sub
name {
my
$self
=
shift
;
$self
->query
unless
$self
->{
'lastquery'
};
return
undef
if
$self
->error;
return
$self
->{
'status'
}{
'upsBasicIdentName'
};
}
sub
load {
my
$self
=
shift
;
$self
->query
unless
$self
->{
'lastquery'
};
return
undef
if
$self
->error;
my
$l
=
$self
->{
'status'
}{
'upsAdvOutputLoad'
}/100;
}
sub
birthday {
my
$self
=
shift
;
$self
->query
unless
$self
->{
'lastquery'
};
return
undef
if
$self
->error;
my
$dt
=
$self
->{
'status'
}{
'upsAdvIdentDateOfManufacture'
};
return
$dt
->ymd;
}
sub
temperature {
my
$self
=
shift
;
$self
->query
unless
$self
->{
'lastquery'
};
return
undef
if
$self
->error;
return
$self
->{
'status'
}{
'upsAdvBatteryTemperature'
};
}
1;