diff --git a/lib/towerops/snmp/poller_worker.ex b/lib/towerops/snmp/poller_worker.ex index 5a69eb14..4a65e839 100644 --- a/lib/towerops/snmp/poller_worker.ex +++ b/lib/towerops/snmp/poller_worker.ex @@ -100,23 +100,34 @@ defmodule Towerops.Snmp.PollerWorker do defp poll_sensors(sensors, client_opts, timestamp) do Enum.each(sensors, fn sensor -> case Client.get(client_opts, sensor.sensor_oid) do - {:ok, raw_value} when is_number(raw_value) -> - # Calculate actual value using divisor - value = raw_value / sensor.sensor_divisor + {:ok, raw_value} -> + decoded_value = decode_snmp_value(raw_value) - # Determine status based on value (could be enhanced with thresholds) - status = "ok" + if is_number(decoded_value) do + # Calculate actual value using divisor + value = decoded_value / sensor.sensor_divisor - # Save the reading - Snmp.create_sensor_reading(%{ - sensor_id: sensor.id, - value: value, - status: status, - checked_at: timestamp - }) + # Determine status based on value (could be enhanced with thresholds) + status = "ok" - {:ok, _non_numeric} -> - Logger.debug("Non-numeric SNMP value for sensor #{sensor.sensor_descr}") + # Save the reading + Snmp.create_sensor_reading(%{ + sensor_id: sensor.id, + value: value, + status: status, + checked_at: timestamp + }) + else + Logger.debug("Non-numeric SNMP value for sensor #{sensor.sensor_descr}") + + # Save reading with nil value + Snmp.create_sensor_reading(%{ + sensor_id: sensor.id, + value: nil, + status: "unknown", + checked_at: timestamp + }) + end {:error, reason} -> Logger.warning("Failed to poll sensor #{sensor.sensor_descr}: #{inspect(reason)}") @@ -160,7 +171,7 @@ defmodule Towerops.Snmp.PollerWorker do results = Enum.map(oids, fn {key, oid} -> case Client.get(client_opts, oid) do - {:ok, value} when is_number(value) -> {key, value} + {:ok, value} -> {key, decode_snmp_value(value)} _ -> {key, nil} end end) @@ -168,6 +179,25 @@ defmodule Towerops.Snmp.PollerWorker do {:ok, Map.new(results)} end + # Decode SNMP values, handling Counter64 and other binary types + defp decode_snmp_value(value) when is_number(value), do: value + + defp decode_snmp_value(value) when is_binary(value) do + # Try to decode as Counter64 (8 bytes, big-endian unsigned integer) + case byte_size(value) do + 8 -> + <> = value + counter + + _ -> + # Unknown binary format, return nil + Logger.debug("Unknown SNMP binary value format, size: #{byte_size(value)}") + nil + end + end + + defp decode_snmp_value(_), do: nil + defp build_client_opts(equipment) do [ ip: equipment.ip_address,