#!/usr/bin/perl # # This uses data in the 'upses' database table (any that use this agent' to get a list of APC-brand UPSes to scan. # # Examples; # # Exit codes; # 0 - Success # 1 - Something went wrong, agent aborted run. # # 255 - The host's UUID isn't in the hosts table yet, ScanCore itself hasn't been run. # # TODO: # - Set a health score if we lose one or both/all UPSes. # - Support UPSes with extended runtime batteries # - Pick a battery temperature where the UPS will automatically shut down if it passes over. # - Add support for sudden temperature jumps in process_temperature(). # - It might be possible that a battery goes over temp, then is removed and not replaced, the UPS could keep # reporting a temp anomoly. # # Use my modules. use strict; use warnings; use Anvil::Tools; use Data::Dumper; use Socket; no warnings 'recursion'; # Disable buffering $| = 1; # Prevent a discrepency between UID/GID and EUID/EGID from throwing an error. $< = $>; $( = $); my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0]; my $running_directory = ($0 =~ /^(.*?)\/$THIS_FILE$/)[0]; if (($running_directory =~ /^\./) && ($ENV{PWD})) { $running_directory =~ s/^\./$ENV{PWD}/; } my $anvil = Anvil::Tools->new(); # Make sure we're running as 'root' # $< == real UID, $> == effective UID if (($< != 0) && ($> != 0)) { # Not root $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, 'print' => 1, key => "error_0005"}); $anvil->nice_exit({exit_code => 1}); } # Get the handle to the AN::Tools and preset some variables I will use. $anvil->data->{'scan-apc-ups'} = { # Starts at '2' so that anything set to '1' manually shows first alert_sort => 2, disable => 0, # By default, a temperature sensor will go into warning state when it goes over this number of °C # below the alert temperature reported by the UPS. temperature_warning_delta => 3, # This is the number of °C below a warning or critical level where an alert is cleared. temperature_clear_delta => 5, # If the temperature jumps by more than this amount in less than set time, an alert will be # generated. This is meant to help detect cooling loss. temperature_jump_threshold => 5, # degrees C temperature_jump_time => 60, # seconds # If the battery charge drops below this level, a warning level alert will be # triggered. low_charge_percentage_warning => 20, # If the battery charge rate climbs above this level, the user will be informed that # the UPS is back to an acceptible charge low_charge_percentage_ok => 25, # This is the number of volts above the low voltage trasfer lever or below the high # voltage transfer level needed to clear the alert. transfer_voltage_clear_delta => 2, # This is the number of scans in a row that an alert state needs to exist for before # we trigger an alarm. sensor_loss_count_to_alarm => 3, # This is the load percentage over which we trigger a high-load alert. high_load_threshold => 80, high_load_clear_threshold => 60, # This is the estimated hold-up time (in seconds) under which we trigger a low-hold-up-time alert. low_hold_up_threshold => 900, low_hold_up_clear_threshold => 1200, }; $anvil->data->{oids} = { battery => { # Estimated next replacement date (in 'mm/dd/yy' or 'mm/dd/yyyy' format.) next_replacement_date => ".1.3.6.1.4.1.318.1.1.1.2.2.21.0", # 1 => OK, 2 => Replacement needed health => ".1.3.6.1.4.1.318.1.1.1.2.2.4.0", model => ".1.3.6.1.4.1.318.1.1.1.2.2.19.0", # High precision, (1000 = 100.0% charge) percentage_charge_hp => ".1.3.6.1.4.1.318.1.1.1.2.3.1.0", # Last approximate replacement date (mm/dd/yy or yyyy format) last_replacement_date => ".1.3.6.1.4.1.318.1.1.1.2.1.3.0", # 1 => unknown, 2 => batteryNormal, 3 => batteryLow, # 4 => batteryInFaultCondition 'state' => ".1.3.6.1.4.1.318.1.1.1.2.1.1.0", # High-precision, (315 == 31.5) temperature_hp => ".1.3.6.1.4.1.318.1.1.1.2.3.2.0", # Temperature alarm upper limit (in even degrees, 40 = 40*C or *F # (see ups::temperature_units)) alarm_temperature => ".1.3.6.1.4.1.318.1.1.10.1.2.2.1.3.1", # High precision voltage (271 = 27.1 vDC) voltage_hp => ".1.3.6.1.4.1.318.1.1.1.2.3.4.0", }, input => { # High precision, (600 == 60.0 Hz) frequency_hp => ".1.3.6.1.4.1.318.1.1.1.3.3.4.0", # 1 => Auto, 2 => Low, 3 => Medium, 4 => High sensitivity => ".1.3.6.1.4.1.318.1.1.1.5.2.7.0", # High precision, (1245 => "124.5 vAC) voltage_hp => ".1.3.6.1.4.1.318.1.1.1.3.3.1.0", # High precision; Maximum and minimum voltage in the last 60 seconds (1245 == 124.5 vAC) '1m_maximum_input_voltage_hp' => ".1.3.6.1.4.1.318.1.1.1.3.3.2.0", '1m_minimum_input_voltage_hp' => ".1.3.6.1.4.1.318.1.1.1.3.3.3.0", }, ups => { # Time in tickss after AC restore before UPS powers on (ie: 1000 = 10 seconds) ac_restore_delay => ".1.3.6.1.4.1.318.1.1.1.5.2.9.0", # How many batteries are in the UPS. battery_count => ".1.3.6.1.4.1.318.1.1.1.2.2.5.0", # Delay time from when the shutdown command is sent until when the UPS # actually powers off (measured in ticks) shutdown_delay => ".1.3.6.1.4.1.318.1.1.1.5.2.10.0", firmware_version => ".1.3.6.1.4.1.318.1.1.1.1.2.1.0", # The modes are documented as 'scan_apc_ups_health_00{01..20}' with # the integer value correlating to the returned health integer value. health => ".1.3.6.1.4.1.318.1.1.1.4.1.1.0", # Voltage at which TRIM ONLINE kicks in (127 == 127 vAC) high_transfer_voltage => ".1.3.6.1.4.1.318.1.1.1.5.2.2.0", # 1 => noTransfer, 2 => highLineVoltage, 3 => brownout, # 4 => blackout, 5 => smallMomentarySag, 6 => deepMomentarySag, # 7 => smallMomentarySpike, 8 => largeMomentarySpike, # 9 => selfTest, 10 => rateOfVoltageChange last_transfer_reason => ".1.3.6.1.4.1.318.1.1.1.3.2.5.0", # Voltage at which BOOST ONLINE kicks in (106 == 106vAC) low_transfer_voltage => ".1.3.6.1.4.1.318.1.1.1.5.2.3.0", # Manufactured date (in 'mm/dd/yy' or 'mm/dd/yyyy' format.) manufactured_date => ".1.3.6.1.4.1.318.1.1.1.1.2.2.0", model => ".1.3.6.1.4.1.318.1.1.1.1.2.5.0", # Temperature units (1 = *C, 2 = *F) temperature_units => ".1.3.6.1.4.1.318.1.1.10.1.2.2.1.5.1", serial_number => ".1.3.6.1.4.1.318.1.1.1.1.2.3.0", # This is used to power off the UPS. Set: # 2 = turnUpsOff (no delay), # 3 = turnUpsOffGracefully (use delay) power_off => ".1.3.6.1.4.1.318.1.1.1.6.2.1.0", }, nmc => { firmware_version => ".1.3.6.1.4.1.318.1.4.2.4.1.4.1", serial_number => ".1.3.6.1.4.1.318.1.4.2.4.1.2.1", mac_address => ".1.3.6.1.2.1.4.30.1.4.2", }, output => { # High precision, Current load percentage (58 = 5.8%) load_percentage_hp => ".1.3.6.1.4.1.318.1.1.1.4.3.3.0", # Time in ticks on batteries, 0 == not on batteries time_on_batteries => ".1.3.6.1.4.1.318.1.1.1.2.1.2.0", # In ticks (10ms) estimated_runtime => ".1.3.6.1.4.1.318.1.1.1.2.2.3.0", # high-precision, (600 == 60.0 Hz) frequency_hp => ".1.3.6.1.4.1.318.1.1.1.4.3.2.0", # High precision (1245 = 124.5 vAC) voltage_hp => ".1.3.6.1.4.1.318.1.1.1.4.3.1.0", # Total output power (in 10 watt-hour increments, divide by 100 # for kW/hr total_output => ".1.3.6.1.4.1.318.1.1.1.4.3.6.0", }, }; $anvil->data->{snmp} = { alternate => { 'SUART' => { }, }, community => { 'read' => "public", version => "2c", 'write' => "private", }, }; $anvil->Storage->read_config(); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "log_0115", variables => { program => $THIS_FILE }}); # Read switches $anvil->Get->switches; # Too many connections cause the UPS to lag out, so we only run on Strikers. my $host_type = $anvil->Get->host_type(); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { host_type => $host_type }}); if (($host_type ne "striker") && (not $anvil->data->{switches}{force})) { $anvil->nice_exit({exit_code => 1}); } # Handle start-up tasks my $problem = $anvil->ScanCore->agent_startup({agent => $THIS_FILE}); if ($problem) { $anvil->nice_exit({exit_code => 1}); } if ($anvil->data->{switches}{purge}) { # This can be called when doing bulk-database purges. my $schema_file = $anvil->data->{path}{directories}{scan_agents}."/".$THIS_FILE."/".$THIS_FILE.".sql"; $anvil->Database->purge_data({ debug => 2, tables => $anvil->Database->get_tables_from_schema({schema_file => $schema_file}), }); $anvil->nice_exit({exit_code => 0}); } # Find the UPSes. The number of UPSes found is returned. If 0, we exit if (not find_upses($anvil)) { # No UPSes found. $anvil->Log->entry({log_level => 1, 'print' => 1, message_key => "scan_apc_ups_message_0001", file => $THIS_FILE, line => __LINE__}); $anvil->nice_exit({exit_code => 1}); } # Read the last state of any UPSes we already know about read_last_scan($anvil); # Gather details on UPSes. gather_ups_data($anvil); # Look for changes. find_changes($anvil); # Shut down. $anvil->ScanCore->agent_shutdown({agent => $THIS_FILE}); ############################################################################################################# # Functions # ############################################################################################################# # This reads in the last scan data from one of the databases and compares it against the just-read data. If # anything changed, register an alert. sub find_changes { my ($anvil) = @_; # This stores all the queries so that they're committed in one transaction. $anvil->data->{sys}{queries} = []; $anvil->data->{'scan-apc-ups'}{alert_sort} = 1; # Loop through each UPS we've seen this pass foreach my $scan_apc_ups_uuid (sort {$a cmp $b} keys %{$anvil->data->{ups}{scan_apc_ups_uuid}}) { my $new_ups = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{new_ups}; my $ups_uuid = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_upses}{scan_apc_ups_ups_uuid}; my $scan_apc_ups_serial_number = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_serial_number}; my $scan_apc_ups_name = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_name}; my $scan_apc_ups_ip = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ip}; my $scan_apc_ups_ac_restore_delay = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ac_restore_delay}; my $scan_apc_ups_shutdown_delay = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_shutdown_delay}; my $scan_apc_ups_firmware_version = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_firmware_version}; my $scan_apc_ups_health = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_health}; my $scan_apc_ups_high_transfer_voltage = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_high_transfer_voltage}; my $scan_apc_ups_low_transfer_voltage = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_low_transfer_voltage}; my $scan_apc_ups_last_transfer_reason = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_last_transfer_reason}; my $scan_apc_ups_manufactured_date = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_manufactured_date}; my $scan_apc_ups_model = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_model}; my $scan_apc_ups_nmc_firmware_version = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_firmware_version}; my $scan_apc_ups_nmc_serial_number = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_serial_number}; my $scan_apc_ups_nmc_mac_address = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_mac_address}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { new_ups => $new_ups, ups_uuid => $ups_uuid, scan_apc_ups_serial_number => $scan_apc_ups_serial_number, scan_apc_ups_ip => $scan_apc_ups_ip, scan_apc_ups_ac_restore_delay => $scan_apc_ups_ac_restore_delay, scan_apc_ups_shutdown_delay => $scan_apc_ups_shutdown_delay, scan_apc_ups_firmware_version => $scan_apc_ups_firmware_version, scan_apc_ups_health => $scan_apc_ups_health, scan_apc_ups_high_transfer_voltage => $scan_apc_ups_high_transfer_voltage, scan_apc_ups_low_transfer_voltage => $scan_apc_ups_low_transfer_voltage, scan_apc_ups_last_transfer_reason => $scan_apc_ups_last_transfer_reason, scan_apc_ups_manufactured_date => $scan_apc_ups_manufactured_date, scan_apc_ups_model => $scan_apc_ups_model, scan_apc_ups_nmc_firmware_version => $scan_apc_ups_nmc_firmware_version, scan_apc_ups_nmc_serial_number => $scan_apc_ups_nmc_serial_number, scan_apc_ups_nmc_mac_address => $scan_apc_ups_nmc_mac_address, }}); # These are loaded now as some variables are needed when examining others from other tables. my $scan_apc_ups_input_1m_minimum_input_voltage = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage}; my $scan_apc_ups_input_1m_maximum_input_voltage = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage}; my $scan_apc_ups_input_voltage = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_voltage}; my $scan_apc_ups_input_sensitivity = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity}; my $scan_apc_ups_input_frequency = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_frequency}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_input_1m_minimum_input_voltage => $scan_apc_ups_input_1m_minimum_input_voltage, scan_apc_ups_input_1m_maximum_input_voltage => $scan_apc_ups_input_1m_maximum_input_voltage, scan_apc_ups_input_voltage => $scan_apc_ups_input_voltage, scan_apc_ups_input_sensitivity => $scan_apc_ups_input_sensitivity, scan_apc_ups_input_frequency => $scan_apc_ups_input_frequency, }}); my $scan_apc_ups_output_voltage = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage}; my $scan_apc_ups_output_total_output = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output}; my $scan_apc_ups_output_frequency = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency}; my $scan_apc_ups_output_time_on_batteries = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries}; my $scan_apc_ups_output_estimated_runtime = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_estimated_runtime}; my $scan_apc_ups_output_load_percentage = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_output_voltage => $scan_apc_ups_output_voltage, scan_apc_ups_output_total_output => $scan_apc_ups_output_total_output, scan_apc_ups_output_frequency => $scan_apc_ups_output_frequency, scan_apc_ups_output_time_on_batteries => $scan_apc_ups_output_time_on_batteries, scan_apc_ups_output_estimated_runtime => $scan_apc_ups_output_estimated_runtime, scan_apc_ups_output_load_percentage => $scan_apc_ups_output_load_percentage, }}); # Have I seen this UPS before? if ($new_ups) { # New, INSERT it. my $query = " INSERT INTO scan_apc_upses ( scan_apc_ups_uuid, scan_apc_ups_ups_uuid, scan_apc_ups_name, scan_apc_ups_ip, scan_apc_ups_ac_restore_delay, scan_apc_ups_shutdown_delay, scan_apc_ups_firmware_version, scan_apc_ups_health, scan_apc_ups_high_transfer_voltage, scan_apc_ups_low_transfer_voltage, scan_apc_ups_last_transfer_reason, scan_apc_ups_manufactured_date, scan_apc_ups_model, scan_apc_ups_serial_number, scan_apc_ups_nmc_firmware_version, scan_apc_ups_nmc_serial_number, scan_apc_ups_nmc_mac_address, modified_date ) VALUES ( ".$anvil->Database->quote($scan_apc_ups_uuid).", ".$anvil->Database->quote($ups_uuid).", ".$anvil->Database->quote($scan_apc_ups_name).", ".$anvil->Database->quote($scan_apc_ups_ip).", ".$anvil->Database->quote($scan_apc_ups_ac_restore_delay).", ".$anvil->Database->quote($scan_apc_ups_shutdown_delay).", ".$anvil->Database->quote($scan_apc_ups_firmware_version).", ".$anvil->Database->quote($scan_apc_ups_health).", ".$anvil->Database->quote($scan_apc_ups_high_transfer_voltage).", ".$anvil->Database->quote($scan_apc_ups_low_transfer_voltage).", ".$anvil->Database->quote($scan_apc_ups_last_transfer_reason).", ".$anvil->Database->quote($scan_apc_ups_manufactured_date).", ".$anvil->Database->quote($scan_apc_ups_model).", ".$anvil->Database->quote($scan_apc_ups_serial_number).", ".$anvil->Database->quote($scan_apc_ups_nmc_firmware_version).", ".$anvil->Database->quote($scan_apc_ups_nmc_serial_number).", ".$anvil->Database->quote($scan_apc_ups_nmc_mac_address).", ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." );"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); my $variables = { name => $scan_apc_ups_name, model => $scan_apc_ups_model, serial_number => $scan_apc_ups_serial_number, manufactured_date => $scan_apc_ups_manufactured_date, firmware_version => $scan_apc_ups_firmware_version, ip_address => $scan_apc_ups_ip, nmc_serial_number => $scan_apc_ups_nmc_serial_number, nmc_firmware_version => $scan_apc_ups_nmc_firmware_version, nmc_mac_address => $scan_apc_ups_nmc_mac_address, ac_restore_delay => $scan_apc_ups_ac_restore_delay, shutdown_delay => $scan_apc_ups_shutdown_delay, health => "#!string!scan_apc_ups_health_".sprintf("%04d", $scan_apc_ups_health)."!#", high_transfer_voltage => $scan_apc_ups_high_transfer_voltage, low_transfer_voltage => $scan_apc_ups_low_transfer_voltage, last_transfer_reason => "#!string!scan_apc_ups_last_xfer_".sprintf("%04d", $scan_apc_ups_last_transfer_reason)."!#", }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_message_0002", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_apc_ups_message_0002", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); # Add any batteries. foreach my $battery_number (sort {$a cmp $b} keys %{$anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}}) { my $scan_apc_ups_battery_uuid = insert_battery($anvil, $scan_apc_ups_uuid, $battery_number); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_battery_uuid => $scan_apc_ups_battery_uuid }}); } # Record input data my $scan_apc_ups_input_uuid = insert_input($anvil, $scan_apc_ups_uuid); # Record output data my $scan_apc_ups_output_uuid = insert_output($anvil, $scan_apc_ups_uuid); } else { # Existing UPS, look for changes. my $old_scan_apc_ups_ups_uuid = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ups_uuid}; my $old_scan_apc_ups_serial_number = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_serial_number}; my $old_scan_apc_ups_name = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_name}; my $old_scan_apc_ups_ip = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ip}; my $old_scan_apc_ups_ac_restore_delay = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ac_restore_delay}; my $old_scan_apc_ups_shutdown_delay = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_shutdown_delay}; my $old_scan_apc_ups_firmware_version = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_firmware_version}; my $old_scan_apc_ups_health = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_health}; my $old_scan_apc_ups_high_transfer_voltage = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_high_transfer_voltage}; my $old_scan_apc_ups_low_transfer_voltage = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_low_transfer_voltage}; my $old_scan_apc_ups_last_transfer_reason = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_last_transfer_reason}; my $old_scan_apc_ups_manufactured_date = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_manufactured_date}; my $old_scan_apc_ups_model = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_model}; my $old_scan_apc_ups_nmc_firmware_version = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_firmware_version}; my $old_scan_apc_ups_nmc_serial_number = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_serial_number}; my $old_scan_apc_ups_nmc_mac_address = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_mac_address}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_scan_apc_ups_ups_uuid => $old_scan_apc_ups_ups_uuid, old_scan_apc_ups_serial_number => $old_scan_apc_ups_serial_number, old_scan_apc_ups_name => $old_scan_apc_ups_name, old_scan_apc_ups_ip => $old_scan_apc_ups_ip, old_scan_apc_ups_ac_restore_delay => $old_scan_apc_ups_ac_restore_delay, old_scan_apc_ups_shutdown_delay => $old_scan_apc_ups_shutdown_delay, old_scan_apc_ups_firmware_version => $old_scan_apc_ups_firmware_version, old_scan_apc_ups_health => $old_scan_apc_ups_health, old_scan_apc_ups_high_transfer_voltage => $old_scan_apc_ups_high_transfer_voltage, old_scan_apc_ups_low_transfer_voltage => $old_scan_apc_ups_low_transfer_voltage, old_scan_apc_ups_last_transfer_reason => $old_scan_apc_ups_last_transfer_reason, old_scan_apc_ups_manufactured_date => $old_scan_apc_ups_manufactured_date, old_scan_apc_ups_model => $old_scan_apc_ups_model, old_scan_apc_ups_nmc_firmware_version => $old_scan_apc_ups_nmc_firmware_version, old_scan_apc_ups_nmc_serial_number => $old_scan_apc_ups_nmc_serial_number, old_scan_apc_ups_nmc_mac_address => $old_scan_apc_ups_nmc_mac_address, }}); my $ups_changed = 0; if ($scan_apc_ups_name ne $old_scan_apc_ups_name) { $ups_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_changed => $ups_changed }}); my $variables = { old_name => $scan_apc_ups_name, new_name => $old_scan_apc_ups_name, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_warning_0005", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_warning_0005", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } if ($scan_apc_ups_serial_number ne $old_scan_apc_ups_serial_number) { # Likely a replacement UPS. $ups_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_changed => $ups_changed }}); my $variables = { ups_name => $scan_apc_ups_name, old_value => $old_scan_apc_ups_serial_number, new_value => $scan_apc_ups_serial_number, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_warning_0006", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_warning_0006", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } if ($scan_apc_ups_ip ne $old_scan_apc_ups_ip) { $ups_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_changed => $ups_changed }}); my $variables = { ups_name => $scan_apc_ups_name, old_value => $old_scan_apc_ups_ip, new_value => $scan_apc_ups_ip, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_warning_0007", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_warning_0007", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } if ($scan_apc_ups_model ne $old_scan_apc_ups_model) { # Likely a replacement UPS. $ups_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_changed => $ups_changed }}); my $variables = { ups_name => $scan_apc_ups_name, old_value => $old_scan_apc_ups_model, new_value => $scan_apc_ups_model, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_warning_0008", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_warning_0008", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } if ($scan_apc_ups_ac_restore_delay ne $old_scan_apc_ups_ac_restore_delay) { $ups_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_changed => $ups_changed }}); my $variables = { ups_name => $scan_apc_ups_name, old_value => $old_scan_apc_ups_ac_restore_delay, new_value => $scan_apc_ups_ac_restore_delay, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_warning_0009", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_warning_0009", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } if ($scan_apc_ups_shutdown_delay ne $old_scan_apc_ups_shutdown_delay) { $ups_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_changed => $ups_changed }}); my $variables = { ups_name => $scan_apc_ups_name, old_value => $old_scan_apc_ups_shutdown_delay, new_value => $scan_apc_ups_shutdown_delay, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_warning_0010", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_warning_0010", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } if ($scan_apc_ups_firmware_version ne $old_scan_apc_ups_firmware_version) { $ups_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_changed => $ups_changed }}); my $variables = { ups_name => $scan_apc_ups_name, old_value => $old_scan_apc_ups_firmware_version, new_value => $scan_apc_ups_firmware_version, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_warning_0011", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_warning_0011", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } # Has the health changed? This is fairly complex as there are many possible health # values. if ($scan_apc_ups_health ne $old_scan_apc_ups_health) { my $level = "notice"; $ups_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_changed => $ups_changed }}); ### There are 20 possible states ### (* == warning, rest are notice): # *1 - The UPS's health is in an unknown state. # 2 - The UPS is operating normally. # 3 - The UPS is running on its batteries. See below for checks if input # voltage remains. If not, this will indicate a power loss event. # 4 - The UPS is compensating for low input power. This is treated as being # on batteries. # 5 - The UPS is in a timed sleep. It will power back on when the timer has # expired. # 6 - The UPS is in bypass-mode and was placed in this mode by software. # Power is passing to downstream devices through a radio frequency # interference filter, but is not conditioned in any other way. Batter # protection is not available. # *7 - The UPS is off. No power is being provided to down-stream equipment. # *8 - The UPS is currently rebooting. # 9 - The UPS is in bypass-mode and was placed in this mode by a hardware # switch. Power is passing to downstream devices through a radio # frequency interference filter, but is not conditioned in any other # way. Batter protection is not available. # 10 - The UPS is in bypass-mode because of an internal failure. Power is # passing to downstream devices through a radio frequency interference # filter, but is not conditioned in any other way. Batter protection is # not available. # *11 - The UPS has lost input power and is sleeping. It will restore output # power once input power has been restored. # 12 - The UPS is compensating for high input voltage. # 13 - The UPS is operating in low-power mode. In this mode, the UPS is in # static bypass mode and it is drawing very little power. If a fault is # detected, it will switch to either normal operation or forced static # bypass mode. # 14 - The UPS is operating in hot-standby mode. # 15 - The UPS is performing a test of its batteries. # *16 - The UPS has been placed in emergency static bypass mode. Power is # passing to downstream devices through a radio frequency interference # filter, but is not conditioned in any other way. Batter protection is # not available. # 17 - The UPS is in static bypass standby mode. It is not currently # providing power to downstream devices. # 18 - The UPS is in power saving mode. The front panel display will be off # but the UPS is operating normally. # 19 - The UPS is in SPoT (Self Power Test) operating mode. # - http://www.apcmedia.com/salestools/COCR-9TZK8N/COCR-9TZK8N_R0_EN.pdf # 20 - The UPS is in ECOnversion mode. The UPS is providing power to the # downstream devices via the bypass. The UPS's inverter is operational # and ready to take over the output load if an input fault occurs. # - http://www.apcmedia.com/salestools/MBPN-9HCLNT/MBPN-9HCLNT_R0_EN.pdf # ----[ Fake ones ]---- # 30 - The UPS is running on batteries but there is still input voltage, but # it is higher than the high transfer voltage so we're TRIMing. # 31 - The UPS is running on batteries but there is still input voltage, but # it is lower than the low transfer voltage so we're BOOSTing # 32 - The UPS is running on batteries but there is still nominal input # voltage, so it is likely a self-test. # Make sure we have a valid health integer my $say_scan_apc_ups_health = $scan_apc_ups_health; my $say_old_scan_apc_ups_health = $old_scan_apc_ups_health; if (($scan_apc_ups_health =~ /\D/) or (($scan_apc_ups_health < 0) or ($scan_apc_ups_health > 20))) { # We'll use '99' as a generic "this is not known" $say_scan_apc_ups_health = 99; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_scan_apc_ups_health => $say_scan_apc_ups_health }}); } elsif (($old_scan_apc_ups_health =~ /\D/) or (($old_scan_apc_ups_health < 0) or ($old_scan_apc_ups_health > 20))) { # We'll use '99' as a generic "this is not known" $say_old_scan_apc_ups_health = 99; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { say_old_scan_apc_ups_health => $say_old_scan_apc_ups_health }}); } # If the UPS is on batteries, check the input voltage. If there is # still power we'll indicate a self-test. if ($scan_apc_ups_health eq "3") { if ($scan_apc_ups_input_voltage > $scan_apc_ups_high_transfer_voltage) { $scan_apc_ups_health = 30; } elsif ($scan_apc_ups_input_voltage < 10) { # Actual power loss. $scan_apc_ups_health = 3; $level = "warning"; } elsif ($scan_apc_ups_input_voltage < $scan_apc_ups_low_transfer_voltage) { $scan_apc_ups_health = 31; } else { $scan_apc_ups_health = 32; } } # Now check if power is back. if ($old_scan_apc_ups_health eq "3") { # Clear the alert. $level = "warning"; } # If the old or new level is one worthy of a warning, set the alert level to # warning. if (($scan_apc_ups_health eq "1") or ($scan_apc_ups_health eq "7") or ($scan_apc_ups_health eq "8") or ($scan_apc_ups_health eq "11") or ($scan_apc_ups_health eq "16")) { # Entered a warning state. $level = "warning"; } elsif (($old_scan_apc_ups_health eq "1") or ($old_scan_apc_ups_health eq "7") or ($old_scan_apc_ups_health eq "8") or ($old_scan_apc_ups_health eq "11") or ($old_scan_apc_ups_health eq "16")) { # Warning state cleared. $level = "warning"; } my $variables = { ups_name => $scan_apc_ups_name, new_value => "#!string!scan_apc_ups_health_".sprintf("%04d", $say_scan_apc_ups_health)."!#", old_value => "#!string!scan_apc_ups_health_".sprintf("%04d", $say_old_scan_apc_ups_health)."!#", }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_warning_0012", variables => $variables}); $anvil->Alert->register({alert_level => $level, message => "scan_apc_ups_warning_0012", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } if ($scan_apc_ups_low_transfer_voltage ne $old_scan_apc_ups_low_transfer_voltage) { $ups_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_changed => $ups_changed }}); # This is a 'notice' level alert. Which message we use will depend on whether # the threshold increased or decreased. my $message_key = "scan_apc_ups_warning_0013"; if ($scan_apc_ups_low_transfer_voltage < $old_scan_apc_ups_low_transfer_voltage) { $message_key = "scan_apc_ups_warning_0014"; } my $variables = { ups_name => $scan_apc_ups_name, new_value => $scan_apc_ups_low_transfer_voltage, old_value => $old_scan_apc_ups_low_transfer_voltage, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => $message_key, variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => $message_key, variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } # Has the last transfer reason changed? There are 10 reasons why this might happen, # some being more critical than others. if ($scan_apc_ups_last_transfer_reason ne $old_scan_apc_ups_last_transfer_reason) { $ups_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_changed => $ups_changed }}); ### NOTE: This used to be 'warning' level, but it caused way too many false ### alarms. If a serious issue arises, the input voltage will trigger a ### 'warning' level alert. ### There are 10 possible states # 0 - There is no information on when the UPS last transferred to battery. # 1 - The UPS has not transferred to battery power since the last time it booted. # 2 - The UPS last transferred to batteries because of high input voltage. # 3 - The UPS last transferred to batteries because of a brown out. That is, a prolonged drop in input voltage from the mains circuit. # 4 - The UPS last transferred to batteries because of a black out. That is, a prolonged loss of input voltage from the mains circuit. # 5 - The UPS last transferred to batteries because of a brief, minor reduction of input voltage from the mains circuit. # 6 - The UPS last transferred to batteries because of a brief, significant reduction of input voltage from the mains circuit. # 7 - The UPS last transferred to batteries because of a brief, minor increase of input voltage from the mains circuit. # 8 - The UPS last transferred to batteries because of a brief, significant spike of input voltage from the mains circuit. # 9 - The UPS last transferred to batteries as part of a planned self-test. # 10 - The UPS last transferred to batteries because of a significant change of input voltage from the mains circuit. # Make sure we have a valid health integer my $say_scan_apc_ups_last_transfer_reason = $scan_apc_ups_last_transfer_reason; my $say_old_scan_apc_ups_last_transfer_reason = $old_scan_apc_ups_last_transfer_reason; if (($scan_apc_ups_last_transfer_reason =~ /\D/) or (($scan_apc_ups_last_transfer_reason < 0) or ($scan_apc_ups_last_transfer_reason > 10))) { # We'll use '99' as a generic "this is not known" $say_scan_apc_ups_last_transfer_reason = 99; } elsif (($old_scan_apc_ups_last_transfer_reason =~ /\D/) or (($old_scan_apc_ups_last_transfer_reason < 0) or ($old_scan_apc_ups_last_transfer_reason > 10))) { # We'll use '99' as a generic "this is not known" $say_old_scan_apc_ups_last_transfer_reason = 99; } # The level of the alert will depends on the now/old state my $log_level = 3; my $alert_level = "info"; if (($scan_apc_ups_last_transfer_reason eq "2") or ($old_scan_apc_ups_last_transfer_reason eq "2") or ($scan_apc_ups_last_transfer_reason eq "3") or ($old_scan_apc_ups_last_transfer_reason eq "3") or ($scan_apc_ups_last_transfer_reason eq "4") or ($old_scan_apc_ups_last_transfer_reason eq "3") or ($scan_apc_ups_last_transfer_reason eq "6") or ($old_scan_apc_ups_last_transfer_reason eq "6") or ($scan_apc_ups_last_transfer_reason eq "8") or ($old_scan_apc_ups_last_transfer_reason eq "8") or ($scan_apc_ups_last_transfer_reason eq "10") or ($old_scan_apc_ups_last_transfer_reason eq "10")) { $log_level = 2; $alert_level = "notice"; } my $variables = { ups_name => $scan_apc_ups_name, new_value => "#!string!scan_apc_ups_last_transfer_".sprintf("%04d", $say_scan_apc_ups_last_transfer_reason)."!#", old_value => "#!string!scan_apc_ups_last_transfer_".sprintf("%04d", $say_old_scan_apc_ups_last_transfer_reason)."!#", }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $log_level, key => "scan_apc_ups_warning_0015", variables => $variables}); $anvil->Alert->register({alert_level => $alert_level, message => "scan_apc_ups_warning_0015", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } if ($scan_apc_ups_manufactured_date ne $old_scan_apc_ups_manufactured_date) { # Likely a replacement UPS. $ups_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_changed => $ups_changed }}); my $variables = { ups_name => $scan_apc_ups_name, old_value => $old_scan_apc_ups_manufactured_date, new_value => $scan_apc_ups_manufactured_date, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_warning_0016", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_warning_0016", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } # Has the NMC's firmware changed? if ($scan_apc_ups_nmc_firmware_version ne $old_scan_apc_ups_nmc_firmware_version) { # NMC was either updated or replaced. $ups_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_changed => $ups_changed }}); my $variables = { ups_name => $scan_apc_ups_name, old_value => $old_scan_apc_ups_nmc_firmware_version, new_value => $scan_apc_ups_nmc_firmware_version, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_warning_0017", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_warning_0017", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } # Has the NMC serial number changed? If the user changed the network card, # this could be triggered. if ($scan_apc_ups_nmc_serial_number ne $old_scan_apc_ups_nmc_serial_number) { # NMC was probably replaced $ups_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_changed => $ups_changed }}); my $variables = { ups_name => $scan_apc_ups_name, old_value => $old_scan_apc_ups_nmc_serial_number, new_value => $scan_apc_ups_nmc_serial_number, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_warning_0018", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_warning_0018", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } # As with above, if the MAC address changed, it is probably because the NMC # was replaced. if ($scan_apc_ups_nmc_mac_address ne $old_scan_apc_ups_nmc_mac_address) { # NMC was probably replaced $ups_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_changed => $ups_changed }}); my $variables = { ups_name => $scan_apc_ups_name, old_value => $old_scan_apc_ups_nmc_mac_address, new_value => $scan_apc_ups_nmc_mac_address, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_warning_0019", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_warning_0019", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } if ($ups_changed) { my $query = " UPDATE scan_apc_upses SET scan_apc_ups_name = ".$anvil->Database->quote($scan_apc_ups_name).", scan_apc_ups_ip = ".$anvil->Database->quote($scan_apc_ups_ip).", scan_apc_ups_serial_number = ".$anvil->Database->quote($scan_apc_ups_serial_number).", scan_apc_ups_ac_restore_delay = ".$anvil->Database->quote($scan_apc_ups_ac_restore_delay).", scan_apc_ups_shutdown_delay = ".$anvil->Database->quote($scan_apc_ups_shutdown_delay).", scan_apc_ups_firmware_version = ".$anvil->Database->quote($scan_apc_ups_firmware_version).", scan_apc_ups_health = ".$anvil->Database->quote($scan_apc_ups_health).", scan_apc_ups_high_transfer_voltage = ".$anvil->Database->quote($scan_apc_ups_high_transfer_voltage).", scan_apc_ups_low_transfer_voltage = ".$anvil->Database->quote($scan_apc_ups_low_transfer_voltage).", scan_apc_ups_last_transfer_reason = ".$anvil->Database->quote($scan_apc_ups_last_transfer_reason).", scan_apc_ups_manufactured_date = ".$anvil->Database->quote($scan_apc_ups_manufactured_date).", scan_apc_ups_model = ".$anvil->Database->quote($scan_apc_ups_model).", scan_apc_ups_nmc_firmware_version = ".$anvil->Database->quote($scan_apc_ups_nmc_firmware_version).", scan_apc_ups_nmc_serial_number = ".$anvil->Database->quote($scan_apc_ups_nmc_serial_number).", scan_apc_ups_nmc_mac_address = ".$anvil->Database->quote($scan_apc_ups_nmc_mac_address).", modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_apc_ups_uuid = ".$anvil->Database->quote($scan_apc_ups_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } # Input changes. This can only change, never come new my $input_changed = 0; my $scan_apc_ups_input_uuid = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_uuid}; my $old_scan_apc_ups_input_sensitivity = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity}; my $old_scan_apc_ups_input_voltage = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_voltage}; my $old_scan_apc_ups_input_1m_maximum_input_voltage = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage}; my $old_scan_apc_ups_input_1m_minimum_input_voltage = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_scan_apc_ups_input_sensitivity => $old_scan_apc_ups_input_sensitivity, old_scan_apc_ups_input_voltage => $old_scan_apc_ups_input_voltage, old_scan_apc_ups_input_1m_maximum_input_voltage => $old_scan_apc_ups_input_1m_maximum_input_voltage, old_scan_apc_ups_input_1m_minimum_input_voltage => $old_scan_apc_ups_input_1m_minimum_input_voltage, }}); # Output changes. This can only change, never come new my $output_changed = 0; my $scan_apc_ups_output_uuid = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_uuid}; my $old_scan_apc_ups_output_load_percentage = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage}; my $old_scan_apc_ups_output_time_on_batteries = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries}; my $old_scan_apc_ups_output_estimated_runtime = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_estimated_runtime}; my $old_scan_apc_ups_output_frequency = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency}; my $old_scan_apc_ups_output_voltage = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage}; my $old_scan_apc_ups_output_total_output = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { old_scan_apc_ups_output_voltage => $old_scan_apc_ups_output_voltage, old_scan_apc_ups_output_total_output => $old_scan_apc_ups_output_total_output, old_scan_apc_ups_output_frequency => $old_scan_apc_ups_output_frequency, old_scan_apc_ups_output_time_on_batteries => $old_scan_apc_ups_output_time_on_batteries, old_scan_apc_ups_output_estimated_runtime => $old_scan_apc_ups_output_estimated_runtime, old_scan_apc_ups_output_load_percentage => $old_scan_apc_ups_output_load_percentage, }}); if ($scan_apc_ups_input_sensitivity ne $old_scan_apc_ups_input_sensitivity) { $input_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { input_changed => $input_changed }}); # Make sure we have a valid health integer my $say_scan_apc_ups_input_sensitivity = $scan_apc_ups_input_sensitivity; my $say_old_scan_apc_ups_input_sensitivity = $old_scan_apc_ups_input_sensitivity; if (($scan_apc_ups_input_sensitivity =~ /\D/) or (($scan_apc_ups_input_sensitivity < 0) or ($scan_apc_ups_input_sensitivity > 4))) { # We'll use '99' as a generic "this is not known" $say_scan_apc_ups_input_sensitivity = 99; } elsif (($old_scan_apc_ups_input_sensitivity =~ /\D/) or (($old_scan_apc_ups_input_sensitivity < 0) or ($old_scan_apc_ups_input_sensitivity > 4))) { # We'll use '99' as a generic "this is not known" $say_old_scan_apc_ups_input_sensitivity = 99; } my $variables = { ups_name => $scan_apc_ups_name, new_value => "#!string!scan_apc_ups_sensitivity_".sprintf("%04d", $say_scan_apc_ups_input_sensitivity)."!#", old_value => "#!string!scan_apc_ups_sensitivity_".sprintf("%04d", $say_old_scan_apc_ups_input_sensitivity)."!#", }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_warning_0020", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_warning_0020", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++}); } # Has the input voltage changed? if ($scan_apc_ups_input_voltage ne $old_scan_apc_ups_input_voltage) { $input_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { input_changed => $input_changed }}); # This is always changing, so normally we will use an 'info' level alert. my $message_key = "scan_apc_ups_warning_0024"; # These are thresholds my $high_transfer_voltage = $scan_apc_ups_high_transfer_voltage; my $clear_high_transfer = ($scan_apc_ups_high_transfer_voltage - $anvil->data->{'scan-apc-ups'}{transfer_voltage_clear_delta}); my $low_transfer_voltage = $scan_apc_ups_low_transfer_voltage; my $clear_low_transfer = ($scan_apc_ups_low_transfer_voltage + $anvil->data->{'scan-apc-ups'}{transfer_voltage_clear_delta}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { high_transfer_voltage => $high_transfer_voltage, clear_high_transfer => $clear_high_transfer, low_transfer_voltage => $low_transfer_voltage, clear_low_transfer => $clear_low_transfer, }}); my $variables = { ups_name => $scan_apc_ups_name, new_value => $anvil->Convert->round({places => 1, number => $scan_apc_ups_input_voltage}), old_value => $anvil->Convert->round({places => 1, number => $old_scan_apc_ups_input_voltage}), holdup_time => $anvil->Convert->time({'time' => $scan_apc_ups_output_estimated_runtime}), high_transfer_voltage => $high_transfer_voltage, clear_high_transfer => $clear_high_transfer, low_transfer_voltage => $low_transfer_voltage, clear_low_transfer => $clear_low_transfer, }; # holdup_time => $anvil->Convert->time({'time' => $scan_apc_ups_output_estimated_runtime}), my $lost_voltage_key = $scan_apc_ups_uuid."::scan_apc_ups_input_voltage_lost"; my $low_voltage_key = $scan_apc_ups_uuid."::scan_apc_ups_input_voltage_low"; my $high_voltage_key = $scan_apc_ups_uuid."::scan_apc_ups_input_voltage_high"; # Is the voltage rising or falling? if ($scan_apc_ups_input_voltage > $old_scan_apc_ups_input_voltage) { ### It is rising. # Has it crossed over the high-voltage transfer threshold? If not, # has it crossed over the low-voltage clear level? if ($old_scan_apc_ups_input_voltage == 0) { # Power has been restored. my $changed = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $lost_voltage_key, set_by => $THIS_FILE }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_ups_warning_0021", variables => $variables}); $anvil->Alert->register({alert_level => "warning", clear_alert => 1, message => "scan_apc_ups_warning_0021", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } elsif ($scan_apc_ups_input_voltage > $high_transfer_voltage) { # Voltage is too high, see if the alert exists already my $changed = $anvil->Alert->check_alert_sent({record_locator => $high_voltage_key, set_by => $THIS_FILE }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_ups_warning_0022", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_apc_ups_warning_0022", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } elsif ($scan_apc_ups_input_voltage > $clear_low_transfer) { # Above the low transfer clear level. my $changed = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $low_voltage_key, set_by => $THIS_FILE }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_ups_warning_0023", variables => $variables}); $anvil->Alert->register({alert_level => "warning", clear_alert => 1, message => "scan_apc_ups_warning_0023", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } } else { # It is falling. $message_key = "scan_apc_ups_warning_0025"; # Has it dropped below the low transfer voltage? If not, has # it dropped below the high-voltage clear level? if ($scan_apc_ups_input_voltage == 0) { # Power lost entirely my $changed = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $lost_voltage_key, set_by => $THIS_FILE }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_ups_warning_0026", variables => $variables}); $anvil->Alert->register({alert_level => "warning", clear_alert => 1, message => "scan_apc_ups_warning_0026", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } elsif ($scan_apc_ups_input_voltage < $low_transfer_voltage) { # It is below the low-transfer limit, set an alert if needed. my $changed = $anvil->Alert->check_alert_sent({record_locator => $low_voltage_key, set_by => $THIS_FILE }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_ups_warning_0027", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_apc_ups_warning_0027", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } elsif ($scan_apc_ups_input_voltage < $clear_high_transfer) { # The voltage is below the high transfer voltage. my $changed = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $high_voltage_key, set_by => $THIS_FILE }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_ups_warning_0028", variables => $variables}); $anvil->Alert->register({alert_level => "warning", clear_alert => 1, message => "scan_apc_ups_warning_0028", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } } $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => $message_key, variables => $variables}); $anvil->Alert->register({alert_level => "info", message => $message_key, variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } # Has the maximum input voltage seen in the last 60 seconds changed? if ($scan_apc_ups_input_1m_maximum_input_voltage ne $old_scan_apc_ups_input_1m_maximum_input_voltage) { # This is expected to always happen. $input_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { input_changed => $input_changed }}); my $variables = { ups_name => $scan_apc_ups_name, new_value => $anvil->Convert->round({places => 1, number => $scan_apc_ups_input_1m_maximum_input_voltage}), old_value => $anvil->Convert->round({places => 1, number => $old_scan_apc_ups_input_1m_maximum_input_voltage}), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_warning_0029", variables => $variables}); $anvil->Alert->register({alert_level => "info", message => "scan_apc_ups_warning_0029", variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } # Has the minimum input voltage seen in the last 60 seconds changed? if ($scan_apc_ups_input_1m_minimum_input_voltage ne $old_scan_apc_ups_input_1m_minimum_input_voltage) { $input_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { input_changed => $input_changed }}); my $variables = { ups_name => $scan_apc_ups_name, new_value => $anvil->Convert->round({places => 1, number => $scan_apc_ups_input_1m_minimum_input_voltage}), old_value => $anvil->Convert->round({places => 1, number => $old_scan_apc_ups_input_1m_minimum_input_voltage}), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_warning_0030", variables => $variables}); $anvil->Alert->register({alert_level => "info", message => "scan_apc_ups_warning_0030", variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { input_changed => $input_changed }}); if ($input_changed) { my $query = " UPDATE scan_apc_ups_input SET scan_apc_ups_input_scan_apc_ups_uuid = ".$anvil->Database->quote($scan_apc_ups_uuid).", scan_apc_ups_input_frequency = ".$anvil->Database->quote($scan_apc_ups_input_frequency).", scan_apc_ups_input_sensitivity = ".$anvil->Database->quote($scan_apc_ups_input_sensitivity).", scan_apc_ups_input_voltage = ".$anvil->Database->quote($scan_apc_ups_input_voltage).", scan_apc_ups_input_1m_maximum_input_voltage = ".$anvil->Database->quote($scan_apc_ups_input_1m_maximum_input_voltage).", scan_apc_ups_input_1m_minimum_input_voltage = ".$anvil->Database->quote($scan_apc_ups_input_1m_minimum_input_voltage).", modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_apc_ups_input_uuid = ".$anvil->Database->quote($scan_apc_ups_input_uuid)." ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } # Look for changes in output data now. if ($scan_apc_ups_output_load_percentage ne $old_scan_apc_ups_output_load_percentage) { $output_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output_changed => $output_changed }}); # Is it rising or falling? my $log_normal = 1; my $high_load_key = $scan_apc_ups_uuid."::scan_apc_ups_high_load"; my $variables = { ups_name => $scan_apc_ups_name, new_value => $scan_apc_ups_output_load_percentage, old_value => $old_scan_apc_ups_output_load_percentage, high_load => $anvil->data->{'scan-apc-ups'}{high_load_threshold}, high_clear => $anvil->data->{'scan-apc-ups'}{high_load_clear_threshold}, }; if ($scan_apc_ups_output_load_percentage > $old_scan_apc_ups_output_load_percentage) { # Rising, is it over the high-load alert? $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { scan_apc_ups_output_load_percentage => $scan_apc_ups_output_load_percentage, "scan-apc-ups::high_load_threshold" => $anvil->data->{'scan-apc-ups'}{high_load_threshold}, }}); if ($scan_apc_ups_output_load_percentage > $anvil->data->{'scan-apc-ups'}{high_load_threshold}) { # Over high load, is this a first? my $changed = $anvil->Alert->check_alert_sent({record_locator => $high_load_key, set_by => $THIS_FILE }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $log_normal = 0; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_ups_warning_0032", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_apc_ups_warning_0032", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } } else { # Falling, is it below the high-load clear threshold? $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { scan_apc_ups_output_load_percentage => $scan_apc_ups_output_load_percentage, "scan-apc-ups::high_load_clear_threshold" => $anvil->data->{'scan-apc-ups'}{high_load_clear_threshold}, }}); if ($scan_apc_ups_output_load_percentage < $anvil->data->{'scan-apc-ups'}{high_load_clear_threshold}) { # It's below the clear high-load value, is this new? my $changed = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $high_load_key, set_by => $THIS_FILE }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $log_normal = 0; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_ups_warning_0033", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_apc_ups_warning_0033", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } } if ($log_normal) { # This is an info level alert as it changes all the time. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_warning_0031", variables => $variables}); $anvil->Alert->register({alert_level => "info", message => "scan_apc_ups_warning_0031", variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } } # Has the time on batteries value changed? if ($scan_apc_ups_output_time_on_batteries ne $old_scan_apc_ups_output_time_on_batteries) { $output_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output_changed => $output_changed }}); # If the old value was '0', we just switched to batteries. This will be a # 'notice' level event. Likewise if the new time is '0'. Otherwise, it is # 'info'. We don't do 'warning' because that is caught by the loss of input # voltage. my $level = "info"; my $message_key = "scan_apc_ups_warning_0034"; my $variables = { ups_name => $scan_apc_ups_name, new_value => $anvil->Convert->time({'time' => $scan_apc_ups_output_time_on_batteries}), old_value => $anvil->Convert->time({'time' => $old_scan_apc_ups_output_time_on_batteries}), }; # Is the old time '0'? if ($scan_apc_ups_output_time_on_batteries eq "0") { # We're on batteries now. $level = "notice"; $message_key = "scan_apc_ups_warning_0035"; } elsif ($old_scan_apc_ups_output_time_on_batteries eq "0") { # We're no longer on batteries. $level = "notice"; $message_key = "scan_apc_ups_warning_0036"; } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { level => $level, message_key => $message_key, }}); $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => $message_key, variables => $variables}); $anvil->Alert->register({alert_level => $level, message => $message_key, variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } # Has the estimated runtime changed? if ($scan_apc_ups_output_estimated_runtime ne $old_scan_apc_ups_output_estimated_runtime) { $output_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output_changed => $output_changed }}); # If the estimated hold-up time is below 15 minutes, send an alert. If the # estimated hold-up time is greater than 20 minutes, clear it. my $send_alert = 1; my $low_hold_up_key = $scan_apc_ups_uuid."::scan_apc_ups_low_holdup_time"; my $variables = { ups_name => $scan_apc_ups_name, new_value => $anvil->Convert->time({'time' => $scan_apc_ups_output_estimated_runtime}), old_value => $anvil->Convert->time({'time' => $old_scan_apc_ups_output_estimated_runtime}), low_threshold => $anvil->Convert->time({'time' => $anvil->data->{'scan-apc-ups'}{low_hold_up_threshold}}), clear_threshold => $anvil->Convert->time({'time' => $anvil->data->{'scan-apc-ups'}{low_hold_up_clear_threshold}}), }; if ($scan_apc_ups_output_estimated_runtime < $anvil->data->{'scan-apc-ups'}{low_hold_up_threshold}) { # Low hold up time, has an alert been sent? my $changed = $anvil->Alert->check_alert_sent({record_locator => $low_hold_up_key, set_by => $THIS_FILE }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $send_alert = 0; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "err", key => "scan_apc_ups_warning_0038", variables => $variables}); $anvil->Alert->register({alert_level => "note", message => "scan_apc_ups_warning_0038", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } elsif ($scan_apc_ups_output_estimated_runtime > $anvil->data->{'scan-apc-ups'}{low_hold_up_clear_threshold}) { # Above the clear threshold, was an alert set? my $changed = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $low_hold_up_key, set_by => $THIS_FILE }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $send_alert = 0; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, priority => "err", key => "scan_apc_ups_warning_0039", variables => $variables}); $anvil->Alert->register({alert_level => "note", clear_alert => 1, message => "scan_apc_ups_warning_0039", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } if ($send_alert) { # A normal minor change. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_warning_0037", variables => $variables}); $anvil->Alert->register({alert_level => "info", message => "scan_apc_ups_warning_0037", variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } } # Has the output frequency changed? if ($scan_apc_ups_output_frequency ne $old_scan_apc_ups_output_frequency) { $output_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output_changed => $output_changed }}); # This changes often, so it's info my $variables = { ups_name => $scan_apc_ups_name, new_value => $anvil->Convert->round({places => 1, number => $scan_apc_ups_output_frequency}), old_value => $anvil->Convert->round({places => 1, number => $old_scan_apc_ups_output_frequency}), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_warning_0040", variables => $variables}); $anvil->Alert->register({alert_level => "info", message => "scan_apc_ups_warning_0040", variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } # Has the output voltage changed? if ($scan_apc_ups_output_voltage ne $old_scan_apc_ups_output_voltage) { $output_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output_changed => $output_changed }}); # This changes often and is generally not a concern. my $variables = { ups_name => $scan_apc_ups_name, new_value => $anvil->Convert->round({places => 1, number => $scan_apc_ups_output_voltage}), old_value => $anvil->Convert->round({places => 1, number => $old_scan_apc_ups_output_voltage}), }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_warning_0041", variables => $variables}); $anvil->Alert->register({alert_level => "info", message => "scan_apc_ups_warning_0041", variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } # This is always changing... if ($scan_apc_ups_output_total_output ne $old_scan_apc_ups_output_total_output) { $output_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output_changed => $output_changed }}); # This changes every scan and is not a concern. my $say_scan_apc_ups_output_total_output = $anvil->Convert->round({places => 2, number => $scan_apc_ups_output_total_output}); $say_scan_apc_ups_output_total_output = $anvil->Convert->add_commas({number => $say_scan_apc_ups_output_total_output}); my $say_old_scan_apc_ups_output_total_output = $anvil->Convert->round({places => 2, number => $old_scan_apc_ups_output_total_output}); $say_old_scan_apc_ups_output_total_output = $anvil->Convert->add_commas({number => $say_old_scan_apc_ups_output_total_output}); my $variables = { ups_name => $scan_apc_ups_name, new_value => $say_scan_apc_ups_output_total_output, old_value => $say_old_scan_apc_ups_output_total_output, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_warning_0042", variables => $variables}); $anvil->Alert->register({alert_level => "info", message => "scan_apc_ups_warning_0042", variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output_changed => $output_changed }}); if ($output_changed) { # Update the DB table my $query = " UPDATE scan_apc_ups_output SET scan_apc_ups_output_scan_apc_ups_uuid = ".$anvil->Database->quote($scan_apc_ups_uuid).", scan_apc_ups_output_load_percentage = ".$anvil->Database->quote($scan_apc_ups_output_load_percentage).", scan_apc_ups_output_time_on_batteries = ".$anvil->Database->quote($scan_apc_ups_output_time_on_batteries).", scan_apc_ups_output_estimated_runtime = ".$anvil->Database->quote($scan_apc_ups_output_estimated_runtime).", scan_apc_ups_output_frequency = ".$anvil->Database->quote($scan_apc_ups_output_frequency).", scan_apc_ups_output_voltage = ".$anvil->Database->quote($scan_apc_ups_output_voltage).", scan_apc_ups_output_total_output = ".$anvil->Database->quote($scan_apc_ups_output_total_output).", modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_apc_ups_output_uuid = ".$anvil->Database->quote($scan_apc_ups_output_uuid)." "; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } # Look for batteries, these can come, go and be replaced. foreach my $battery_number (sort {$a cmp $b} keys %{$anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}}) { my $scan_apc_ups_battery_uuid = ""; my $scan_apc_ups_battery_next_replacement_date = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_next_replacement_date}; my $scan_apc_ups_battery_health = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_health}; my $scan_apc_ups_battery_model = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_model}; my $scan_apc_ups_battery_percentage_charge = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_percentage_charge}; my $scan_apc_ups_battery_last_replacement_date = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_last_replacement_date}; my $scan_apc_ups_battery_state = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_state}; my $scan_apc_ups_battery_temperature = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_temperature}; my $scan_apc_ups_battery_alarm_temperature = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_alarm_temperature}; my $scan_apc_ups_battery_voltage = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_voltage}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_battery_next_replacement_date => $scan_apc_ups_battery_next_replacement_date, scan_apc_ups_battery_health => $scan_apc_ups_battery_health, scan_apc_ups_battery_model => $scan_apc_ups_battery_model, scan_apc_ups_battery_percentage_charge => $scan_apc_ups_battery_percentage_charge, scan_apc_ups_battery_last_replacement_date => $scan_apc_ups_battery_last_replacement_date, scan_apc_ups_battery_state => $scan_apc_ups_battery_state, scan_apc_ups_battery_temperature => $scan_apc_ups_battery_temperature, scan_apc_ups_battery_alarm_temperature => $scan_apc_ups_battery_alarm_temperature, scan_apc_ups_battery_voltage => $scan_apc_ups_battery_voltage, }}); if (exists $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery_number}{$battery_number}{scan_apc_ups_battery_uuid}) { $scan_apc_ups_battery_uuid = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery_number}{$battery_number}{scan_apc_ups_battery_uuid}; my $old_scan_apc_ups_battery_next_replacement_date = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_next_replacement_date}; my $old_scan_apc_ups_battery_health = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_health}; my $old_scan_apc_ups_battery_model = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_model}; my $old_scan_apc_ups_battery_percentage_charge = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_percentage_charge}; my $old_scan_apc_ups_battery_last_replacement_date = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_last_replacement_date}; my $old_scan_apc_ups_battery_state = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_state}; my $old_scan_apc_ups_battery_temperature = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_temperature}; my $old_scan_apc_ups_battery_alarm_temperature = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_alarm_temperature}; my $old_scan_apc_ups_battery_voltage = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_voltage}; my $last_update_unixtime = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{last_update_unixtime}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_battery_uuid => $scan_apc_ups_battery_uuid, old_scan_apc_ups_battery_next_replacement_date => $old_scan_apc_ups_battery_next_replacement_date, old_scan_apc_ups_battery_health => $old_scan_apc_ups_battery_health, old_scan_apc_ups_battery_model => $old_scan_apc_ups_battery_model, old_scan_apc_ups_battery_percentage_charge => $old_scan_apc_ups_battery_percentage_charge, old_scan_apc_ups_battery_last_replacement_date => $old_scan_apc_ups_battery_last_replacement_date, old_scan_apc_ups_battery_state => $old_scan_apc_ups_battery_state, old_scan_apc_ups_battery_temperature => $old_scan_apc_ups_battery_temperature, old_scan_apc_ups_battery_alarm_temperature => $old_scan_apc_ups_battery_alarm_temperature, old_scan_apc_ups_battery_voltage => $old_scan_apc_ups_battery_voltage, last_update_unixtime => $last_update_unixtime, }}); # Looks for changes my $battery_changed = 0; # Has the estimated replacement date changed? if ($scan_apc_ups_battery_next_replacement_date ne $old_scan_apc_ups_battery_next_replacement_date) { $battery_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { battery_changed => $battery_changed }}); # This changes often with load shifts, so it's an info alert. my $variables = { ups_name => $scan_apc_ups_name, new_value => $scan_apc_ups_battery_next_replacement_date, old_value => $old_scan_apc_ups_battery_next_replacement_date, battery_number => $battery_number, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_message_0008", variables => $variables}); $anvil->Alert->register({alert_level => "info", message => "scan_apc_ups_message_0008", variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } # Has the battery health changed? if ($scan_apc_ups_battery_health ne $old_scan_apc_ups_battery_health) { $battery_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { battery_changed => $battery_changed }}); my $bad_value = ""; my $level = "notice"; my $message_key = "scan_apc_ups_message_0009"; # Make sure we have a valid health integer my $say_scan_apc_ups_battery_health = $scan_apc_ups_battery_health; my $say_old_scan_apc_ups_battery_health = $old_scan_apc_ups_battery_health; if (($scan_apc_ups_battery_health =~ /\D/) or (($scan_apc_ups_battery_health < 0) or ($scan_apc_ups_battery_health > 2))) { # We'll use '99' as a generic "this is not known" $bad_value = $scan_apc_ups_battery_health; $scan_apc_ups_battery_health = 99; } elsif (($old_scan_apc_ups_battery_health =~ /\D/) or (($old_scan_apc_ups_battery_health < 0) or ($old_scan_apc_ups_battery_health > 2))) { # We'll use '99' as a generic "this is not known" $bad_value = $old_scan_apc_ups_battery_health; $old_scan_apc_ups_battery_health = 99; } ### There are 2 possible states (* == warning): # 1 - The UPS battery is healthy. # *2 - The UPS battery has failed and needs to be replaced. if ($scan_apc_ups_battery_health eq "2") { # Entered a warning state. $level = "warning"; $message_key = "scan_apc_ups_message_0010"; } elsif ($old_scan_apc_ups_battery_health eq "2") { # Warning state cleared. $level = "warning"; $message_key = "scan_apc_ups_message_0011"; } my $sort_position = $level eq "warning" ? 1 : $anvil->data->{'scan-apc-ups'}{alert_sort}++; my $variables = { ups_name => $scan_apc_ups_name, battery_number => $battery_number, bad_value => $bad_value, new_value => "#!string!scan_apc_ups_battery_health_".sprintf("%04d", $say_scan_apc_ups_battery_health)."!#", old_value => "#!string!scan_apc_ups_battery_health_".sprintf("%04d", $say_old_scan_apc_ups_battery_health)."!#", battery_model => $scan_apc_ups_battery_model, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => $message_key, variables => $variables}); $anvil->Alert->register({alert_level => $level, message => $message_key, variables => $variables, sort_position => $sort_position, set_by => $THIS_FILE}); } # Has the battery model changed? if ($scan_apc_ups_battery_model ne $old_scan_apc_ups_battery_model) { # This is almost certainly an event the admin knows about. $battery_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { battery_changed => $battery_changed }}); my $variables = { battery_number => $battery_number, ups_name => $scan_apc_ups_name, new_value => $scan_apc_ups_battery_model, old_value => $old_scan_apc_ups_battery_model, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_message_0012", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_message_0012", variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } # If the battery charge percentage has changed, it will usually be an 'info' # level event, unless it drops below the warning threshold, climbs above the # OK threshold or hits 100% if ($scan_apc_ups_battery_percentage_charge ne $old_scan_apc_ups_battery_percentage_charge) { $battery_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { battery_changed => $battery_changed }}); my $low_charge_key = $scan_apc_ups_uuid."::battery-".$battery_number."::scan_apc_ups_low_charge"; my $level = "info"; my $message_key = "scan_apc_ups_note_0022"; my $alert_sent = 0; my $variables = { ups_name => $scan_apc_ups_name, new_value => $scan_apc_ups_battery_percentage_charge, old_value => $old_scan_apc_ups_battery_percentage_charge, battery_number => $battery_number, low_charge_clear => $anvil->data->{'scan-apc-ups'}{low_charge_percentage_ok}, low_charge_alert => $anvil->data->{'scan-apc-ups'}{low_charge_percentage_warning}, }; # Is the battery charging or discharging? if ($scan_apc_ups_battery_percentage_charge > $old_scan_apc_ups_battery_percentage_charge) { # Charging if ($scan_apc_ups_battery_percentage_charge eq "100") { # For cases where the UPS's input voltage # often drops a little below the low-transfer # volage, causing frequent small discharge/ # charge cycles, we don't want to constantly # sent "battery has charged" alerts. To # handle this, we check to see how long ago # the input voltage was less than half the # low transfer voltage. my $low_limit = int($scan_apc_ups_low_transfer_voltage / 2); $low_limit = 0 if $low_limit =~ /\D/; $low_limit = 0 if $low_limit < 0; my $query = " SELECT round(extract(epoch from modified_date)) FROM scan_apc_ups_input WHERE scan_apc_ups_input_scan_apc_ups_uuid = ".$anvil->Database->quote($scan_apc_ups_uuid)." AND scan_apc_ups_input_1m_minimum_input_voltage < ".$low_limit." ORDER BY modified_date DESC LIMIT 1 ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); # Do the query... my $last_power_loss = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0]; $last_power_loss = 0 if not defined $last_power_loss; my $current_time = time; my $difference = ($current_time - $last_power_loss); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { last_power_loss => $last_power_loss, current_time => $current_time, difference => $difference, }}); # if it's less than six hours, well assume it has finished charging. if ($difference < 21600) { $level = "notice"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { level => $level }}); } else { $level = "info"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { level => $level }}); } $message_key = "scan_apc_ups_message_0013"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { message_key => $message_key }}); } elsif ($scan_apc_ups_battery_percentage_charge > $anvil->data->{'scan-apc-ups'}{low_charge_percentage_ok}) { # Crossed the "now OK" threshold. Was there an alert? # If so, tell the user. my $changed = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $low_charge_key, set_by => $THIS_FILE }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $alert_sent = 1; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_ups_message_0014", variables => $variables}); $anvil->Alert->register({alert_level => "warning", clear_alert => 1, message => "scan_apc_ups_message_0014", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } } else { # Discharging $message_key = "scan_apc_ups_message_0015"; if ($scan_apc_ups_battery_percentage_charge < $anvil->data->{'scan-apc-ups'}{low_charge_percentage_warning}) { # Crossed the "oh crap" threshold. Is this the first # time? 'set' is set to 1 if so. my $changed = $anvil->Alert->check_alert_sent({record_locator => $low_charge_key, set_by => $THIS_FILE }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $alert_sent = 1; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_ups_message_0016", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_apc_ups_message_0016", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } } # If we didn't send a threshold alert, send a normal alert now. $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { alert_sent => $alert_sent }}); if (not $alert_sent) { my $sort_position = $level eq "warning" ? 1 : $anvil->data->{'scan-apc-ups'}{alert_sort}++; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => $message_key, variables => $variables}); $anvil->Alert->register({alert_level => $level, message => $message_key, variables => $variables, sort_position => $sort_position, set_by => $THIS_FILE}); } } # Has the replacement date changed? if ($scan_apc_ups_battery_last_replacement_date ne $old_scan_apc_ups_battery_last_replacement_date) { $battery_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { battery_changed => $battery_changed }}); my $variables = { ups_name => $scan_apc_ups_name, new_value => $scan_apc_ups_battery_last_replacement_date, old_value => $old_scan_apc_ups_battery_last_replacement_date, battery_number => $battery_number, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_message_0017", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_message_0017", variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } # Has the battery state changed? There are four possible battery states. if ($scan_apc_ups_battery_state ne $old_scan_apc_ups_battery_state) { $battery_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { battery_changed => $battery_changed }}); my $level = "notice"; my $message_key = "scan_apc_ups_message_0018"; my $clear_alert = 0; ### There are four possible states (* == warning): # *1 - The UPS battery is in an unknown state. # 2 - The UPS battery is operating normally. # 3 - The UPS battery is in a low voltage state. # *4 - The UPS battery is in a failed state and needs to be replaced. # Make sure we have a valid health integer my $say_scan_apc_ups_battery_state = $scan_apc_ups_battery_state; my $say_old_scan_apc_ups_battery_state = $old_scan_apc_ups_battery_state; if (($scan_apc_ups_battery_state =~ /\D/) or (($scan_apc_ups_battery_state < 0) or ($scan_apc_ups_battery_state > 4))) { # We'll use '99' as a generic "this is not known" $say_scan_apc_ups_battery_state = 99; } elsif (($old_scan_apc_ups_battery_state =~ /\D/) or (($old_scan_apc_ups_battery_state < 0) or ($old_scan_apc_ups_battery_state > 4))) { # We'll use '99' as a generic "this is not known" $say_old_scan_apc_ups_battery_state = 99; } if (($scan_apc_ups_battery_state eq "1") or ($scan_apc_ups_battery_state eq "4")) { # Entered a warning state. $level = "warning"; } elsif (($old_scan_apc_ups_battery_state eq "1") or ($old_scan_apc_ups_battery_state eq "4")) { # Warning state cleared. $level = "warning"; $message_key = "scan_apc_ups_message_0019"; $clear_alert = 1; } my $sort_position = $level eq "warning" ? 1 : $anvil->data->{'scan-apc-ups'}{alert_sort}++; my $variables = { ups_name => $scan_apc_ups_name, new_value => "#!string!scan_apc_ups_battery_state_".sprintf("%04d", $say_scan_apc_ups_battery_state)."!#", old_value => "#!string!scan_apc_ups_battery_state_".sprintf("%04d", $say_old_scan_apc_ups_battery_state)."!#", battery_model => $scan_apc_ups_battery_model, battery_number => $battery_number, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => $message_key, variables => $variables}); $anvil->Alert->register({alert_level => $level, clear_alert => $clear_alert, message => $message_key, variables => $variables, sort_position => $sort_position, set_by => $THIS_FILE}); } # Has the battery's temperature changed? Alerts will be processed # later (in process_alerts() below). Here, we just log the change as # an info level alert. if ($scan_apc_ups_battery_temperature ne $old_scan_apc_ups_battery_temperature) { $battery_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { battery_changed => $battery_changed }}); my $send_alert = 1; # Did the temperature jump? if ($scan_apc_ups_battery_alarm_temperature > $old_scan_apc_ups_battery_alarm_temperature) { my $difference = $scan_apc_ups_battery_alarm_temperature - $old_scan_apc_ups_battery_alarm_temperature; my $time_span = time - $last_update_unixtime; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { difference => $difference, time_span => $time_span, "scan-apc-ups::temperature_jump_threshold" => $anvil->data->{'scan-apc-ups'}{temperature_jump_threshold}, "scan-apc-ups::temperature_jump_time" => $anvil->data->{'scan-apc-ups'}{temperature_jump_time}, }}); if (($difference >= $anvil->data->{'scan-apc-ups'}{temperature_jump_threshold}) && ($time_span <= $anvil->data->{'scan-apc-ups'}{temperature_jump_time})) { # Send a temp jump alert. $send_alert = 0; my $variables = { ups_name => $scan_apc_ups_name, new_value => $scan_apc_ups_battery_alarm_temperature, old_value => $old_scan_apc_ups_battery_alarm_temperature, battery_number => $battery_number, difference => $difference, time_span => $time_span, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_message_0023", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_message_0023", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { send_alert => $send_alert }}); if ($send_alert) { my $variables = { ups_name => $scan_apc_ups_name, new_value => $scan_apc_ups_battery_temperature, old_value => $old_scan_apc_ups_battery_temperature, battery_number => $battery_number, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_message_0020", variables => $variables}); $anvil->Alert->register({alert_level => "info", message => "scan_apc_ups_message_0020", variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } } # Has the alarm temperature changed? if ($scan_apc_ups_battery_alarm_temperature ne $old_scan_apc_ups_battery_alarm_temperature) { $battery_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { battery_changed => $battery_changed }}); my $variables = { ups_name => $scan_apc_ups_name, new_value => $scan_apc_ups_battery_alarm_temperature, old_value => $old_scan_apc_ups_battery_alarm_temperature, battery_number => $battery_number, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_message_0021", variables => $variables}); $anvil->Alert->register({alert_level => "notice", message => "scan_apc_ups_message_0021", variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } # Has the UPS battery voltage changed? if ($scan_apc_ups_battery_voltage ne $old_scan_apc_ups_battery_voltage) { $battery_changed = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { battery_changed => $battery_changed }}); # This is normal and is therefor an info level alert. my $variables = { ups_name => $scan_apc_ups_name, new_value => $anvil->Convert->round({places => 1, number => $scan_apc_ups_battery_voltage}), old_value => $anvil->Convert->round({places => 1, number => $old_scan_apc_ups_battery_voltage}), battery_number => $battery_number, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 2, key => "scan_apc_ups_message_0022", variables => $variables}); $anvil->Alert->register({alert_level => "info", message => "scan_apc_ups_message_0022", variables => $variables, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, set_by => $THIS_FILE}); } $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { battery_changed => $battery_changed }}); if ($battery_changed) { # Save the changes. my $query = " UPDATE scan_apc_ups_batteries SET scan_apc_ups_battery_scan_apc_ups_uuid = ".$anvil->Database->quote($scan_apc_ups_uuid).", scan_apc_ups_battery_number = ".$anvil->Database->quote($battery_number).", scan_apc_ups_battery_next_replacement_date = ".$anvil->Database->quote($scan_apc_ups_battery_next_replacement_date).", scan_apc_ups_battery_health = ".$anvil->Database->quote($scan_apc_ups_battery_health).", scan_apc_ups_battery_model = ".$anvil->Database->quote($scan_apc_ups_battery_model).", scan_apc_ups_battery_percentage_charge = ".$anvil->Database->quote($scan_apc_ups_battery_percentage_charge).", scan_apc_ups_battery_last_replacement_date = ".$anvil->Database->quote($scan_apc_ups_battery_last_replacement_date).", scan_apc_ups_battery_state = ".$anvil->Database->quote($scan_apc_ups_battery_state).", scan_apc_ups_battery_temperature = ".$anvil->Database->quote($scan_apc_ups_battery_temperature).", scan_apc_ups_battery_alarm_temperature = ".$anvil->Database->quote($scan_apc_ups_battery_alarm_temperature).", scan_apc_ups_battery_voltage = ".$anvil->Database->quote($scan_apc_ups_battery_voltage).", modified_date = ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." WHERE scan_apc_ups_battery_uuid = ".$anvil->Database->quote($scan_apc_ups_battery_uuid)." "; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); } } else { # New battery $scan_apc_ups_battery_uuid = insert_battery($anvil, $scan_apc_ups_uuid, $battery_number); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_battery_uuid => $scan_apc_ups_battery_uuid }}); } # Check battery temperatures. process_temperature($anvil, $scan_apc_ups_battery_uuid, $battery_number, $scan_apc_ups_uuid); } } # If the UPS health is '4' (boosting for low input voltage), or if there is no input voltage, # we'll set that we're on batteries. my $scan_apc_ups_on_battery = 0; if (($scan_apc_ups_input_voltage eq "0") or ($scan_apc_ups_health eq "4")) { $scan_apc_ups_on_battery = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_health => $scan_apc_ups_health, scan_apc_ups_input_voltage => $scan_apc_ups_input_voltage, scan_apc_ups_on_battery => $scan_apc_ups_on_battery, }}); } my $power_uuid = $anvil->Database->insert_or_update_power({ debug => 3, power_ups_uuid => $ups_uuid, power_on_battery => $scan_apc_ups_on_battery, power_seconds_left => $scan_apc_ups_output_estimated_runtime, power_charge_percentage => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{highest_charge_percent}, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { power_uuid => $power_uuid }}); } return(0); } # This reads in the last scan's data. sub read_last_scan { my ($anvil) = @_; # Read in existing data, if any. my $query = " SELECT scan_apc_ups_uuid, scan_apc_ups_ups_uuid, scan_apc_ups_serial_number, scan_apc_ups_name, scan_apc_ups_ip, scan_apc_ups_ac_restore_delay, scan_apc_ups_shutdown_delay, scan_apc_ups_firmware_version, scan_apc_ups_health, scan_apc_ups_high_transfer_voltage, scan_apc_ups_low_transfer_voltage, scan_apc_ups_last_transfer_reason, scan_apc_ups_manufactured_date, scan_apc_ups_model, scan_apc_ups_nmc_firmware_version, scan_apc_ups_nmc_serial_number, scan_apc_ups_nmc_mac_address FROM scan_apc_upses ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { results => $results, count => $count, }}); # One or more records were found. foreach my $row (@{$results}) { my $scan_apc_ups_uuid = $row->[0]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { scan_apc_ups_uuid => $scan_apc_ups_uuid }}); $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ups_uuid} = $row->[1]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_serial_number} = $row->[2]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_name} = $row->[3]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ip} = $row->[4]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ac_restore_delay} = $row->[5]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_shutdown_delay} = $row->[6]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_firmware_version} = $row->[7]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_health} = $row->[8]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_high_transfer_voltage} = $row->[9]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_low_transfer_voltage} = $row->[10]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_last_transfer_reason} = $row->[11]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_manufactured_date} = $row->[12]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_model} = $row->[13]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_firmware_version} = $row->[14]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_serial_number} = $row->[15]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_mac_address} = $row->[16]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_ups_uuid" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ups_uuid}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_serial_number" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_serial_number}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_name" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_name}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_ip" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ip}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_ac_restore_delay" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ac_restore_delay}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_shutdown_delay" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_shutdown_delay}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_firmware_version" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_firmware_version}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_health" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_health}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_high_transfer_voltage" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_high_transfer_voltage}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_low_transfer_voltage" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_low_transfer_voltage}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_last_transfer_reason" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_last_transfer_reason}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_manufactured_date" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_manufactured_date}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_model" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_model}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_nmc_firmware_version" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_firmware_version}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_nmc_serial_number" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_serial_number}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_nmc_mac_address" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_mac_address}, }}); # Make it possible to find the UPS by ups_uuid and by serial number. my $scan_apc_ups_ups_uuid = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ups_uuid}; my $scan_apc_ups_serial_number = $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_serial_number}; $anvil->data->{sql}{ups_uuid_to_apc_ups_uuid}{$scan_apc_ups_ups_uuid} = $scan_apc_ups_uuid; $anvil->data->{sql}{serial_number_to_apc_ups_uuid}{$scan_apc_ups_serial_number} = $scan_apc_ups_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sql::ups_uuid_to_apc_ups_uuid::${scan_apc_ups_ups_uuid}" => $anvil->data->{sql}{ups_uuid_to_apc_ups_uuid}{$scan_apc_ups_ups_uuid}, "sql::serial_number_to_apc_ups_uuid::${scan_apc_ups_serial_number}" => $anvil->data->{sql}{serial_number_to_apc_ups_uuid}{$scan_apc_ups_serial_number}, }}); } undef $results; # Read in the battery data $query = " SELECT scan_apc_ups_battery_uuid, scan_apc_ups_battery_scan_apc_ups_uuid, scan_apc_ups_battery_number, scan_apc_ups_battery_next_replacement_date, scan_apc_ups_battery_health, scan_apc_ups_battery_model, scan_apc_ups_battery_percentage_charge, scan_apc_ups_battery_last_replacement_date, scan_apc_ups_battery_state, scan_apc_ups_battery_temperature, scan_apc_ups_battery_alarm_temperature, scan_apc_ups_battery_voltage, round(extract(epoch from modified_date)) FROM scan_apc_ups_batteries ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); # Do the query against the source DB and loop through the results. $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { my $scan_apc_ups_battery_uuid = $row->[0]; my $scan_apc_ups_uuid = $row->[1]; my $scan_apc_ups_battery_number = $row->[2]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_battery_uuid => $scan_apc_ups_battery_uuid, scan_apc_ups_uuid => $scan_apc_ups_uuid, scan_apc_ups_battery_number => $scan_apc_ups_battery_number, }}); $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_next_replacement_date} = $row->[3]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_health} = $row->[4]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_model} = $row->[5]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_percentage_charge} = $row->[6]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_last_replacement_date} = $row->[7]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_state} = $row->[8]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_temperature} = $row->[9]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_alarm_temperature} = $row->[10]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_voltage} = $row->[11]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{last_update_unixtime} = $row->[12]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_battery_uuid::${scan_apc_ups_battery_uuid}::scan_apc_ups_battery_next_replacement_date" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_next_replacement_date}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_battery_uuid::${scan_apc_ups_battery_uuid}::scan_apc_ups_battery_health" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_health}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_battery_uuid::${scan_apc_ups_battery_uuid}::scan_apc_ups_battery_model" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_model}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_battery_uuid::${scan_apc_ups_battery_uuid}::scan_apc_ups_battery_percentage_charge" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_percentage_charge}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_battery_uuid::${scan_apc_ups_battery_uuid}::scan_apc_ups_battery_last_replacement_date" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_last_replacement_date}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_battery_uuid::${scan_apc_ups_battery_uuid}::scan_apc_ups_battery_state" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_state}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_battery_uuid::${scan_apc_ups_battery_uuid}::scan_apc_ups_battery_temperature" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_temperature}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_battery_uuid::${scan_apc_ups_battery_uuid}::scan_apc_ups_battery_alarm_temperature" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_alarm_temperature}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_battery_uuid::${scan_apc_ups_battery_uuid}::scan_apc_ups_battery_voltage" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{scan_apc_ups_battery_voltage}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_battery_uuid::${scan_apc_ups_battery_uuid}::last_update_unixtime" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_battery_uuid}{$scan_apc_ups_battery_uuid}{last_update_unixtime}, }}); $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery_number}{$scan_apc_ups_battery_number}{scan_apc_ups_battery_uuid} = $scan_apc_ups_battery_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery_number::${scan_apc_ups_battery_number}::scan_apc_ups_battery_uuid" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery_number}{$scan_apc_ups_battery_number}{scan_apc_ups_battery_uuid}, }}); } undef $results; # Read in the input voltage data $query = " SELECT scan_apc_ups_input_uuid, scan_apc_ups_input_scan_apc_ups_uuid, scan_apc_ups_input_frequency, scan_apc_ups_input_sensitivity, scan_apc_ups_input_voltage, scan_apc_ups_input_1m_maximum_input_voltage, scan_apc_ups_input_1m_minimum_input_voltage FROM scan_apc_ups_input ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }}); # Do the query against the source DB and loop through the results. $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { my $scan_apc_ups_uuid = $row->[1]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { scan_apc_ups_uuid => $scan_apc_ups_uuid }}); $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_uuid} = $row->[0]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_frequency} = $row->[2]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity} = $row->[3]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_voltage} = $row->[4]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage} = $row->[5]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage} = $row->[6]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_uuid" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_uuid}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_frequency" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_frequency}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_sensitivity" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_voltage" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_voltage}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_1m_maximum_input_voltage" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_1m_minimum_input_voltage" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage}, }}); } undef $results; # And finally, the output voltage data $query = " SELECT scan_apc_ups_output_uuid, scan_apc_ups_output_scan_apc_ups_uuid, scan_apc_ups_output_load_percentage, scan_apc_ups_output_time_on_batteries, scan_apc_ups_output_estimated_runtime, scan_apc_ups_output_frequency, scan_apc_ups_output_voltage, scan_apc_ups_output_total_output FROM scan_apc_ups_output ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { query => $query }}); # Do the query against the source DB and loop through the results. $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { my $scan_apc_ups_uuid = $row->[1]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { scan_apc_ups_uuid => $scan_apc_ups_uuid }}); $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_uuid} = $row->[0]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage} = $row->[2]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries} = $row->[3]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_estimated_runtime} = $row->[4]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency} = $row->[5]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage} = $row->[6]; $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output} = $row->[7]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_uuid" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_uuid}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_load_percentage" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_time_on_batteries" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_estimated_runtime" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_estimated_runtime}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_frequency" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_voltage" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage}, "sql::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_total_output" => $anvil->data->{sql}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output}, }}); } undef $results; return(0); } # This calls each UPS, first to get the model number and update the OIDs to use if needed, then gathers the # information from the UPS. sub gather_ups_data { my ($anvil) = @_; ### TODO: If the network with the UPS is congested, it is possible that, despite connecting to the ### UPS, some OID reads may fail with '#!no_connection!#'. Try to read them a second time in ### these cases. Regardless, be sure to check all returned OID values for 'no connection' and ### handle such cases more gracefully. # Loop through the UPSes we found in upses. foreach my $ups_uuid (sort {$a cmp $b} keys %{$anvil->data->{upses}{ups_uuid}}) { my $ups_ip = $anvil->data->{upses}{ups_uuid}{$ups_uuid}{ip_address}; my $ups_name = $anvil->data->{upses}{ups_uuid}{$ups_uuid}{name}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_uuid => $ups_uuid, ups_ip => $ups_ip, ups_name => $ups_name, }}); # Have we seen this UPS before? my $scan_apc_ups_uuid = ""; my $new_ups = 1; if ((exists $anvil->data->{sql}{ups_uuid_to_apc_ups_uuid}{$ups_uuid}) && (defined $anvil->data->{sql}{ups_uuid_to_apc_ups_uuid}{$ups_uuid})) { # Yup! $scan_apc_ups_uuid = $anvil->data->{sql}{ups_uuid_to_apc_ups_uuid}{$ups_uuid}; $new_ups = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_uuid => $scan_apc_ups_uuid, new_ups => $new_ups, }}); } # Can I ping it? This returns '1' if it was pingable, '0' if not. my ($pinged, $average_time) = $anvil->Network->ping({ping => $ups_ip, debug => 2}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { pinged => $pinged, average_time => $average_time, }}); if (not $pinged) { # Can't reach it. $anvil->data->{upses}{ups_uuid}{$ups_uuid}{ping} = 0; $anvil->data->{upses}{ups_uuid}{$ups_uuid}{connected} = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "upses::ups_uuid::${ups_uuid}::ping" => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{ping}, "upses::ups_uuid::${ups_uuid}::connected" => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{connected}, }}); next; } ### NOTE: At this time, we've only seen SNMP v2c, but it's possible we may need to test other ### versions on a per-UPS bases down the road. $anvil->data->{upses}{ups_uuid}{$ups_uuid}{ping} = 1; $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version} = $anvil->data->{snmp}{community}{version}; $anvil->data->{upses}{ups_uuid}{$ups_uuid}{scan_apc_ups_uuid} = $scan_apc_ups_uuid; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "upses::ups_uuid::${ups_uuid}::ping" => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{ping}, "upses::ups_uuid::${ups_uuid}::snmp_version" => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, "upses::ups_uuid::${ups_uuid}::scan_apc_ups_uuid" => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{scan_apc_ups_uuid}, }}); my ($scan_apc_ups_serial_number, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{ups}{serial_number}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_serial_number => $scan_apc_ups_serial_number, data_type => $data_type, }}); # If the serial number is '!!no_connection!!', this isn't the UPS we want or SNMP is disabled. if ($scan_apc_ups_serial_number eq "!!no_connection!!") { $scan_apc_ups_serial_number = ""; $anvil->data->{upses}{ups_uuid}{$ups_uuid}{connected} = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_serial_number => $scan_apc_ups_serial_number, "upses::ups_uuid::${ups_uuid}::connected" => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{connected}, }}); } # If we didn't find the UPS using the ups_uuid, see if we can find it by the serial number. if ($new_ups) { if (($scan_apc_ups_serial_number) && (exists $anvil->data->{sql}{serial_number_to_apc_ups_uuid}{$scan_apc_ups_serial_number})) { # It's new, generate the UUID now. We'll set 'scan_apc_ups_new' so we know to INSERT # it later. $scan_apc_ups_uuid = $anvil->data->{sql}{serial_number_to_apc_ups_uuid}{$scan_apc_ups_serial_number}; $new_ups = 0; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_uuid => $scan_apc_ups_uuid, new_ups => $new_ups, }}); } else { # It's new, generate the UUID now. We'll set 'scan_apc_ups_new' so we know to INSERT # it later. $scan_apc_ups_uuid = $anvil->Get->uuid(); $new_ups = 1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_uuid => $scan_apc_ups_uuid, new_ups => $new_ups, }}); } } # These are set to avoid 'undefined' variable warnings later if we fail to reach this UPS. $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{highest_charge_percent} = 0; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{new_ups} = $new_ups; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_upses}{scan_apc_ups_ups_uuid} = $ups_uuid; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_serial_number} = $scan_apc_ups_serial_number; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_name} = $ups_name; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ip} = $ups_ip; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ac_restore_delay} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_shutdown_delay} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_firmware_version} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_health} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_high_transfer_voltage} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_low_transfer_voltage} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_last_transfer_reason} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_manufactured_date} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_model} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_firmware_version} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_serial_number} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_mac_address} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_frequency} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage} = ""; # If I got the serial number, I found the UPS. next if not $scan_apc_ups_serial_number; # Now that I can trust my OIDs, lets start gathering data! Keep track of how long it took to # query the OIDs. ############################################################################################# # Base UPS info # ############################################################################################# # Get the AC restore delay, if set. (High-precision, divide by 10 to get seconds). ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ac_restore_delay}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{ups}{ac_restore_delay}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_ac_restore_delay" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ac_restore_delay}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ac_restore_delay} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ac_restore_delay} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_ac_restore_delay", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ac_restore_delay}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ac_restore_delay} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_ac_restore_delay" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_ac_restore_delay}, }}); } # Get the shut down delay, if set. (in ticks, divide by 100). ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_shutdown_delay}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{ups}{shutdown_delay}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_shutdown_delay" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_shutdown_delay}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_shutdown_delay} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_shutdown_delay} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_shutdown_delay", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_shutdown_delay}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_shutdown_delay} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_shutdown_delay" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_shutdown_delay}, }}); } # Get the UPS's firmware version. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_firmware_version}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{ups}{firmware_version}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_firmware_version} =~ s/^\s+//; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_firmware_version} =~ s/\s+$//; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_firmware_version" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_firmware_version}, data_type => $data_type, }}); ### Gather the main UPS data. The returned integer value maps to the appropriate ### 'scan_apc_ups_health_00xx' string. # 1 => Unknown, 2 => Online, 3 => On Battery, # 4 => onSmartBoost, 5 => timedSleeping, 6 => softwareBypass, # 7 => off, 8 => rebooting, 9 => switchedBypass, # 10 => hardwareFailureBypass, 11 => sleepingUntilPowerReturn, # 12 => onSmartTrim, 13 => ecoMode, 14 => hotStandby, # 15 => onBatteryTest, 15 => emergencyStaticBypass, # 17 => staticBypassStandby, 18 => powerSavingMode, # 19 => spotMode, 20 => eConversion ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_health}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{ups}{health}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_health" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_health}, data_type => $data_type, }}); # Get the high and low transfer voltages. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_high_transfer_voltage}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{ups}{high_transfer_voltage}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_high_transfer_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_high_transfer_voltage}, data_type => $data_type, }}); ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_low_transfer_voltage}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{ups}{low_transfer_voltage}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_low_transfer_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_low_transfer_voltage}, data_type => $data_type, }}); ### Get the last transfer reason. The returned integer maps to the appropriate ### 'scan_apc_ups_last_transfer_00xx' string. # 1 => noTransfer, 2 => highLineVoltage, 3 => brownout, # 4 => blackout, 5 => smallMomentarySag, 6 => deepMomentarySag, # 7 => smallMomentarySpike, 8 => largeMomentarySpike, # 9 => selfTest, 10 => rateOfVoltageChange ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_last_transfer_reason}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{ups}{last_transfer_reason}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_last_transfer_reason" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_last_transfer_reason}, data_type => $data_type, }}); # Get the manufacture date of the UPS. This really should never change, but we need to record # it at least once. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_manufactured_date}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{ups}{manufactured_date}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_manufactured_date" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_manufactured_date}, data_type => $data_type, }}); # Convert the format. $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_manufactured_date} = $anvil->Convert->format_mmddyy_to_yymmdd({date => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_manufactured_date}}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_manufactured_date" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_manufactured_date}, }}); # Get the model of the UPS. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_model}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{ups}{model}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_model" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_model}, data_type => $data_type, }}); # Get the temperature units. 1 == C, 2 == F ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_temperature_units}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{ups}{temperature_units}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_temperature_units" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_temperature_units}, data_type => $data_type, }}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_temperature_units} = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_temperature_units} eq "2" ? "F" : "C"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_temperature_units" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_temperature_units}, }}); # If the UPS was replaced, these values could change ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_serial_number}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{ups}{serial_number}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_serial_number" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_serial_number}, data_type => $data_type, }}); ############################################################################################# # NMC information # ############################################################################################# # Get the NMC firmware. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_firmware_version}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{nmc}{firmware_version}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_nmc_firmware_version" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_firmware_version}, data_type => $data_type, }}); # Get the NMC serial number. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_serial_number}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{nmc}{serial_number}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_nmc_serial_number" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_serial_number}, data_type => $data_type, }}); # Now the MAC address. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_mac_address}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{nmc}{mac_address}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_nmc_mac_address" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_mac_address}, data_type => $data_type, }}); # Convert the MAC format. $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_mac_address} =~ s/([0-9a-fA-F]{2}) ([0-9a-fA-F]{2}) ([0-9a-fA-F]{2}) ([0-9a-fA-F]{2}) ([0-9a-fA-F]{2}) ([0-9a-fA-F]{2})/$1:$2:$3:$4:$5:$6/g; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_nmc_mac_address" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_nmc_mac_address}, }}); ############################################################################################# # Battery information # ############################################################################################# # NOTE: In the future, we'll try to read multi-battery UPSes. For now, this is basically a # place-holder. Also note; There is no unique identifiers for UPS batteries. So we # simply track them by sequence number (possibly tied to the OID, to be determined...) foreach my $battery_number (1..1) { $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_next_replacement_date} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_health} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_model} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_percentage_charge} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_last_replacement_date} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_state} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_temperature} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_alarm_temperature} = ""; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_voltage} = ""; # Read the estimated battery replacement date. This only has value if the user remembered to # mark the date the battery was replaced. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_next_replacement_date}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{battery}{next_replacement_date}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_next_replacement_date" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_next_replacement_date}, data_type => $data_type, }}); # Convert the date format $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_next_replacement_date} = $anvil->Convert->format_mmddyy_to_yymmdd({date => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_next_replacement_date}}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_next_replacement_date" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_next_replacement_date}, }}); # Read the battery's health. 1 == OK, 2 == Failed, replace. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_health}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{battery}{health}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_health" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_health}, data_type => $data_type, }}); # Read the battery's model number. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_model}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{battery}{model}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_model" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_model}, data_type => $data_type, }}); # Read the percentage charge. This is high-precision, so divide by 10 to get the actual # percentage (ie: 1000 == 100.0%). ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_percentage_charge}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{battery}{percentage_charge_hp}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_percentage_charge" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_percentage_charge}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_percentage_charge} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_percentage_charge} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_percentage_charge", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_percentage_charge}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_percentage_charge} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_percentage_charge" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_percentage_charge}, }}); } $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_percentage_charge} /= 10; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_percentage_charge" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_percentage_charge}, }}); if ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_percentage_charge} > $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{highest_charge_percent}) { $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{highest_charge_percent} = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_percentage_charge}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::highest_charge_percent" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{highest_charge_percent}, }}); } # Get the date that the UPS was last replaced. (mm/dd/yy or yyyy format) ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_last_replacement_date}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{battery}{last_replacement_date}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_last_replacement_date" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_last_replacement_date}, data_type => $data_type, }}); # Convert the format. $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_last_replacement_date} = $anvil->Convert->format_mmddyy_to_yymmdd({date => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_last_replacement_date}}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_last_replacement_date" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_last_replacement_date}, }}); ### The battery state is expressed as an integer and maps to 'scan_apc_ups_battery_000x'. # 1 => unknown, 2 => batteryNormal, 3 => batteryLow, # 4 => batteryInFaultCondition ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_state}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{battery}{'state'}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_state" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_state}, data_type => $data_type, }}); # This is the temperature of the UPS battery. It is high-precision, so divide by 10 to get # the actual temperature. It is always celsius, so don't convert it. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_temperature}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{battery}{temperature_hp}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_temperature" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_temperature}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_temperature} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_temperature} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_temperature", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_temperature}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_temperature} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_temperature" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_temperature}, }}); } $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_temperature} /= 10; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_temperature" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_temperature}, }}); # Get the temperature at which the system throws a fit. This is stated as a standard integer, # no need to divide by 10. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_alarm_temperature}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{battery}{alarm_temperature}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_alarm_temperature" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_alarm_temperature}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_alarm_temperature} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_alarm_temperature} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_alarm_temperature", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_alarm_temperature}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_alarm_temperature} = 40 ; $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_temperature_units} = "C"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_alarm_temperature" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_alarm_temperature}, "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_temperature_units" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_temperature_units}, }}); } if ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_temperature_units} eq "F") { # We live in a metric world! $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_alarm_temperature} = $anvil->Convert->fahrenheit_to_celsius({temperature => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_alarm_temperature}}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_alarm_temperature" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_alarm_temperature}, }}); } # Read the current battery voltage (vDC). It is a high-precision value, so divide by 10. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_voltage}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{battery}{temperature_hp}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_voltage}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_voltage} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_voltage} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_voltage", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_voltage}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_voltage} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_voltage}, }}); } $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_voltage} /= 10; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::battery::${battery_number}::scan_apc_ups_battery_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_voltage}, }}); } ############################################################################################# # Input Information # ############################################################################################# # This is the current input frequency. It is high-precision, so divide by 10. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_frequency}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{input}{frequency_hp}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_frequency" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_frequency}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_frequency} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_frequency} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_frequency", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_frequency}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_frequency} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_frequency" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_frequency}, }}); } $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_frequency} /= 10; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_frequency" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_frequency}, }}); ### The input sensitivity is an integer that maps to 'scan_apc_ups_sensitivity_000x'. If the ### UPS is an 'online' (dual-conversion model), this will return '0'. # 1 => Auto, 2 => Low, 3 => Medium, 4 => High # We set this to '0' if no value was returned to indicate an 'Online' UPS. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{input}{sensitivity}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_sensitivity" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_sensitivity", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_sensitivity" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity}, }}); } $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity} /= 10; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_sensitivity" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity}, }}); # High-precision input voltage ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_voltage}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{input}{voltage_hp}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_voltage}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_voltage} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_voltage} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_voltage", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_voltage}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_voltage} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_voltage}, }}); } $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_voltage} /= 10; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_voltage}, }}); # High-precision maximum and minimum input voltages (vAC) over the last 60 seconds. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{input}{'1m_maximum_input_voltage_hp'}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_1m_maximum_input_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_1m_maximum_input_voltage", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_1m_maximum_input_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage}, }}); } $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage} /= 10; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_1m_maximum_input_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage}, }}); ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{input}{'1m_minimum_input_voltage_hp'}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_1m_minimum_input_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_1m_minimum_input_voltage", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_1m_minimum_input_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage}, }}); } $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage} /= 10; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_input_1m_minimum_input_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage}, }}); ############################################################################################# # Output Information # ############################################################################################# # High-precision output load percentage, divide by 10. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{output}{load_percentage_hp}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_load_percentage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_load_percentage", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_load_percentage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage}, }}); } $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage} /= 10; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_load_percentage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage}, }}); # The time (in ticks, divide by 100) that the UPS has been running on batteries. '0' # indicates that it is not on batteries. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{output}{time_on_batteries}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_time_on_batteries" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_time_on_batteries", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_time_on_batteries" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries}, }}); } $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries} /= 100; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_time_on_batteries" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries}, }}); ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_estimated_runtime}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{output}{estimated_runtime}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_estimated_runtime" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_estimated_runtime}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_estimated_runtime} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_estimated_runtime} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_estimated_runtime", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_estimated_runtime}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_estimated_runtime} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_estimated_runtime" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_estimated_runtime}, }}); } $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_estimated_runtime} /= 100; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_estimated_runtime" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_estimated_runtime}, }}); # This is the high-precision output frequency in Hz (divide by 10). ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{output}{frequency_hp}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_frequency" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_frequency", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_frequency" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency}, }}); } $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency} /= 10; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_frequency" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency}, }}); # High-precision output voltage (vAC, divide by 10). ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{output}{voltage_hp}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_voltage", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage}, }}); } $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage} /= 10; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_voltage" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage}, }}); # This is the total power outputted since the UPS was created. It is measured in tens of # watt-hours, so divide be 100 to get kW/hr. ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output}, $data_type) = $anvil->Remote->read_snmp_oid({ debug => 3, target => $ups_ip, oid => $anvil->data->{oids}{output}{total_output}, version => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{snmp_version}, community => $anvil->data->{snmp}{community}{'read'} }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_total_output" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output}, data_type => $data_type, }}); if (($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output} eq "--") or ($anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output} =~ /\D/)) { $anvil->Log->entry({log_level => 1, message_key => "scan_apc_ups_error_0001", variables => { name => "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_total_output", value => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output}, }, file => $THIS_FILE, line => __LINE__}); $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output} = -1; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_total_output" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output}, }}); } $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output} /= 100; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "ups::scan_apc_ups_uuid::${scan_apc_ups_uuid}::scan_apc_ups_output_total_output" => $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output}, }}); } return(0); } # This looks for APC UPSes. sub find_upses { my ($anvil) = @_; ### TODO: On nodes and DR hosts, limit this to the UPSes selected as powering the given machine. # Search in 'upses' for UPSes using this scan agent. These aren't bound to hosts (or even Anvil! # systems), so not all may be available. my $query = " SELECT ups_uuid, ups_name, ups_ip_address FROM upses WHERE ups_agent = ".$anvil->Database->quote($THIS_FILE)." ORDER BY ups_name ASC ;"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); my $results = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__}); my $count = @{$results}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { results => $results, count => $count, }}); foreach my $row (@{$results}) { my $ups_uuid = $row->[0]; my $ups_name = $row->[1]; my $ups_ip_address = $row->[2]; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { ups_uuid => $ups_uuid, ups_name => $ups_name, ups_ip_address => $ups_ip_address, }}); $anvil->data->{upses}{ups_uuid}{$ups_uuid}{name} = $ups_name; $anvil->data->{upses}{ups_uuid}{$ups_uuid}{ip_address} = $ups_ip_address; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "upses::ups_uuid::${ups_uuid}::name" => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{name}, "upses::ups_uuid::${ups_uuid}::ip_address" => $anvil->data->{upses}{ups_uuid}{$ups_uuid}{ip_address}, }}); } my $ups_count = keys %{$anvil->data->{upses}{ups_uuid}}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_count => $ups_count }}); return($ups_count); } sub insert_battery { my ($anvil, $scan_apc_ups_uuid, $battery_number) = @_; my $scan_apc_ups_name = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_name}; my $scan_apc_ups_battery_next_replacement_date = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_next_replacement_date}; my $scan_apc_ups_battery_health = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_health}; my $scan_apc_ups_battery_model = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_model}; my $scan_apc_ups_battery_percentage_charge = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_percentage_charge}; my $scan_apc_ups_battery_last_replacement_date = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_last_replacement_date}; my $scan_apc_ups_battery_state = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_state}; my $scan_apc_ups_battery_temperature = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_temperature}; my $scan_apc_ups_battery_alarm_temperature = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_alarm_temperature}; my $scan_apc_ups_battery_voltage = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_voltage}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_battery_next_replacement_date => $scan_apc_ups_battery_next_replacement_date, scan_apc_ups_battery_health => $scan_apc_ups_battery_health, scan_apc_ups_battery_model => $scan_apc_ups_battery_model, scan_apc_ups_battery_percentage_charge => $scan_apc_ups_battery_percentage_charge, scan_apc_ups_battery_last_replacement_date => $scan_apc_ups_battery_last_replacement_date, scan_apc_ups_battery_state => $scan_apc_ups_battery_state, scan_apc_ups_battery_temperature => $scan_apc_ups_battery_temperature, scan_apc_ups_battery_alarm_temperature => $scan_apc_ups_battery_alarm_temperature, scan_apc_ups_battery_voltage => $scan_apc_ups_battery_voltage, }}); my $scan_apc_ups_battery_uuid = $anvil->Get->uuid; my $query = " INSERT INTO scan_apc_ups_batteries ( scan_apc_ups_battery_uuid, scan_apc_ups_battery_scan_apc_ups_uuid, scan_apc_ups_battery_number, scan_apc_ups_battery_next_replacement_date, scan_apc_ups_battery_health, scan_apc_ups_battery_model, scan_apc_ups_battery_percentage_charge, scan_apc_ups_battery_last_replacement_date, scan_apc_ups_battery_state, scan_apc_ups_battery_temperature, scan_apc_ups_battery_alarm_temperature, scan_apc_ups_battery_voltage, modified_date ) VALUES ( ".$anvil->Database->quote($scan_apc_ups_battery_uuid).", ".$anvil->Database->quote($scan_apc_ups_uuid).", ".$anvil->Database->quote($battery_number).", ".$anvil->Database->quote($scan_apc_ups_battery_next_replacement_date).", ".$anvil->Database->quote($scan_apc_ups_battery_health).", ".$anvil->Database->quote($scan_apc_ups_battery_model).", ".$anvil->Database->quote($scan_apc_ups_battery_percentage_charge).", ".$anvil->Database->quote($scan_apc_ups_battery_last_replacement_date).", ".$anvil->Database->quote($scan_apc_ups_battery_state).", ".$anvil->Database->quote($scan_apc_ups_battery_temperature).", ".$anvil->Database->quote($scan_apc_ups_battery_alarm_temperature).", ".$anvil->Database->quote($scan_apc_ups_battery_voltage).", ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." );"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); my $variables = { ups_name => $scan_apc_ups_name, battery_number => $battery_number, replacement_date => $scan_apc_ups_battery_next_replacement_date, health => "#!string!scan_apc_ups_battery_health_".sprintf("%04d", $scan_apc_ups_battery_health)."!#", model => $scan_apc_ups_battery_model, charge_percentage => $scan_apc_ups_battery_percentage_charge, install_date => $scan_apc_ups_battery_last_replacement_date, 'state' => "#!string!scan_apc_ups_battery_state_".sprintf("%04d", $scan_apc_ups_battery_state)."!#", temperature => $scan_apc_ups_battery_temperature, alarm_temperature => $scan_apc_ups_battery_alarm_temperature, voltage => $scan_apc_ups_battery_voltage, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_message_0003", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_ups_message_0003", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, }); return($scan_apc_ups_battery_uuid); } sub insert_input { my ($anvil, $scan_apc_ups_uuid) = @_; my $scan_apc_ups_name = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_name}; my $scan_apc_ups_input_uuid = $anvil->Get->uuid; my $scan_apc_ups_input_1m_minimum_input_voltage = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_minimum_input_voltage}; my $scan_apc_ups_input_1m_maximum_input_voltage = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_1m_maximum_input_voltage}; my $scan_apc_ups_input_voltage = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_voltage}; my $scan_apc_ups_input_sensitivity = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_sensitivity}; my $scan_apc_ups_input_frequency = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_input_frequency}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_input_1m_minimum_input_voltage => $scan_apc_ups_input_1m_minimum_input_voltage, scan_apc_ups_input_1m_maximum_input_voltage => $scan_apc_ups_input_1m_maximum_input_voltage, scan_apc_ups_input_sensitivity => $scan_apc_ups_input_sensitivity, scan_apc_ups_input_frequency => $scan_apc_ups_input_frequency, }}); my $query = " INSERT INTO scan_apc_ups_input ( scan_apc_ups_input_uuid, scan_apc_ups_input_scan_apc_ups_uuid, scan_apc_ups_input_frequency, scan_apc_ups_input_sensitivity, scan_apc_ups_input_voltage, scan_apc_ups_input_1m_maximum_input_voltage, scan_apc_ups_input_1m_minimum_input_voltage, modified_date ) VALUES ( ".$anvil->Database->quote($scan_apc_ups_input_uuid).", ".$anvil->Database->quote($scan_apc_ups_uuid).", ".$anvil->Database->quote($scan_apc_ups_input_frequency).", ".$anvil->Database->quote($scan_apc_ups_input_sensitivity).", ".$anvil->Database->quote($scan_apc_ups_input_voltage).", ".$anvil->Database->quote($scan_apc_ups_input_1m_maximum_input_voltage).", ".$anvil->Database->quote($scan_apc_ups_input_1m_minimum_input_voltage).", ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." );"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); my $variables = { ups_name => $scan_apc_ups_name, '1m_minimum_input_voltage' => $scan_apc_ups_input_1m_minimum_input_voltage, '1m_maximum_input_voltage' => $scan_apc_ups_input_1m_maximum_input_voltage, scan_apc_ups_input_voltage => $scan_apc_ups_input_voltage, input_sensitivity => $scan_apc_ups_input_sensitivity, input_frequency => $scan_apc_ups_input_frequency, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_message_0004", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_ups_message_0004", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, }); return($scan_apc_ups_input_uuid); } sub insert_output { my ($anvil, $scan_apc_ups_uuid) = @_; my $scan_apc_ups_name = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_name}; my $scan_apc_ups_output_uuid = $anvil->Get->uuid; my $scan_apc_ups_output_voltage = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_voltage}; my $scan_apc_ups_output_total_output = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_total_output}; my $scan_apc_ups_output_frequency = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_frequency}; my $scan_apc_ups_output_time_on_batteries = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_time_on_batteries}; my $scan_apc_ups_output_estimated_runtime = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_estimated_runtime}; my $scan_apc_ups_output_load_percentage = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_output_load_percentage}; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { scan_apc_ups_output_voltage => $scan_apc_ups_output_voltage, scan_apc_ups_output_total_output => $scan_apc_ups_output_total_output, scan_apc_ups_output_frequency => $scan_apc_ups_output_frequency, scan_apc_ups_output_time_on_batteries => $scan_apc_ups_output_time_on_batteries, scan_apc_ups_output_estimated_runtime => $scan_apc_ups_output_estimated_runtime, scan_apc_ups_output_load_percentage => $scan_apc_ups_output_load_percentage, }}); my $query = " INSERT INTO scan_apc_ups_output ( scan_apc_ups_output_uuid, scan_apc_ups_output_scan_apc_ups_uuid, scan_apc_ups_output_load_percentage, scan_apc_ups_output_time_on_batteries, scan_apc_ups_output_estimated_runtime, scan_apc_ups_output_frequency, scan_apc_ups_output_voltage, scan_apc_ups_output_total_output, modified_date ) VALUES ( ".$anvil->Database->quote($scan_apc_ups_output_uuid).", ".$anvil->Database->quote($scan_apc_ups_uuid).", ".$anvil->Database->quote($scan_apc_ups_output_load_percentage).", ".$anvil->Database->quote($scan_apc_ups_output_time_on_batteries).", ".$anvil->Database->quote($scan_apc_ups_output_estimated_runtime).", ".$anvil->Database->quote($scan_apc_ups_output_frequency).", ".$anvil->Database->quote($scan_apc_ups_output_voltage).", ".$anvil->Database->quote($scan_apc_ups_output_total_output).", ".$anvil->Database->quote($anvil->Database->refresh_timestamp)." );"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }}); $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__}); my $variables = { ups_name => $scan_apc_ups_name, voltage => $scan_apc_ups_output_voltage, total_output => $scan_apc_ups_output_total_output, time_on_batteries => $scan_apc_ups_output_time_on_batteries ? "#!string!scan_apc_ups_message_0007!#" : "#!string!scan_apc_ups_message_0006!#", load_percentage => $scan_apc_ups_output_load_percentage, }; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "scan_apc_ups_message_0005", variables => $variables}); $anvil->Alert->register({ alert_level => "warning", message => "scan_apc_ups_message_0005", variables => $variables, set_by => $THIS_FILE, sort_position => $anvil->data->{'scan-apc-ups'}{alert_sort}++, }); return($scan_apc_ups_name); } sub process_temperature { my ($anvil, $scan_apc_ups_battery_uuid, $battery_number, $scan_apc_ups_uuid) = @_; ### TODO: Left off here, may have delta, warning and critical mixed up. my $ups_uuid = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_upses}{scan_apc_ups_ups_uuid}; my $ups_name = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{scan_apc_ups_name}; my $battery_temperature = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_temperature}; my $critical_temperature = $anvil->data->{ups}{scan_apc_ups_uuid}{$scan_apc_ups_uuid}{battery}{$battery_number}{scan_apc_ups_battery_alarm_temperature}; my $warning_temperature = ($critical_temperature - $anvil->data->{'scan-apc-ups'}{temperature_warning_delta}); my $clear_critical_temperature = ($critical_temperature - $anvil->data->{'scan-apc-ups'}{temperature_clear_delta}); my $clear_warning_temperature = ($warning_temperature - $anvil->data->{'scan-apc-ups'}{temperature_clear_delta}); my $warning_temp_key = "scan-apc-ups::".$scan_apc_ups_battery_uuid."::warning_temperature"; my $critical_temp_key = "scan-apc-ups::".$scan_apc_ups_battery_uuid."::critical_temperature"; my $temperature_state = "ok"; my $temperature_is = "nominal"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { ups_uuid => $ups_uuid, ups_name => $ups_name, battery_temperature => $battery_temperature, critical_temperature => $critical_temperature, warning_temperature => $warning_temperature, clear_critical_temperature => $clear_critical_temperature, clear_warning_temperature => $clear_warning_temperature, warning_temp_key => $warning_temp_key, critical_temp_key => $critical_temp_key, }}); my $variables = { ups_name => $ups_name, battery_number => $battery_number, temperature => $battery_temperature, warning_temp => $warning_temperature, critical_temperature => $critical_temperature, clear_critical_temp => $clear_critical_temperature, clear_warning_temp => $clear_warning_temperature, }; if ($battery_temperature > $critical_temperature) { # Critically high. Is this new? (also set the warning temp) $anvil->Alert->check_alert_sent({clear => 0, record_locator => $warning_temp_key, set_by => $THIS_FILE }); my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $critical_temp_key, set_by => $THIS_FILE }); $temperature_state = "critical"; $temperature_is = "high"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { temperature_state => $temperature_state, temperature_is => $temperature_is. changed => $changed, }}); if ($changed) { # Register an alert. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_ups_warning_0001", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_apc_ups_warning_0001", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } elsif ($battery_temperature > $critical_temperature) { # Above warning, is this new? my $changed = $anvil->Alert->check_alert_sent({clear => 0, record_locator => $warning_temp_key, set_by => $THIS_FILE }); $temperature_state = "warning"; $temperature_is = "high"; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { temperature_state => $temperature_state, temperature_is => $temperature_is. changed => $changed, }}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_ups_warning_0003", variables => $variables}); $anvil->Alert->register({alert_level => "warning", message => "scan_apc_ups_warning_0003", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } # Any alerts to clear? if ($battery_temperature < $clear_warning_temperature) { # If we had a warning alert, clear it (and critical, in case the temp dropped from critical to clear in one loop). $anvil->Alert->check_alert_sent({clear => 1, record_locator => $critical_temp_key, set_by => $THIS_FILE }); my $changed = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $warning_temp_key, set_by => $THIS_FILE }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_ups_warning_0004", variables => $variables}); $anvil->Alert->register({alert_level => "warning", clear_alert => 1, message => "scan_apc_ups_warning_0004", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } elsif ($battery_temperature < $clear_critical_temperature) { ### NOTE: It's possible that the temperature has dropped from critical to warning. So we're ### only clearing the critical alert. # If we had a critical alert, clear it. my $changed = $anvil->Alert->check_alert_sent({clear => 1, record_locator => $critical_temp_key, set_by => $THIS_FILE }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { changed => $changed }}); if ($changed) { # Register an alert. $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "scan_apc_ups_warning_0002", variables => $variables}); $anvil->Alert->register({alert_level => "warning", clear_alert => 1, message => "scan_apc_ups_warning_0002", variables => $variables, sort_position => 1, set_by => $THIS_FILE}); } } my $temperature_uuid = $anvil->Database->insert_or_update_temperature({ debug => 3, temperature_agent_name => $THIS_FILE, temperature_sensor_host => $ups_uuid, temperature_sensor_name => "ups_battery_temperature", temperature_value_c => $battery_temperature, temperature_state => $temperature_state, temperature_is => $temperature_is, temperature_weight => 1, }); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { temperature_uuid => $temperature_uuid }}); return(0); }