diff --git a/lib/towerops/snmp/profiles/vendors/routeros.ex b/lib/towerops/snmp/profiles/vendors/routeros.ex index 23fbac0f..d3191e8f 100644 --- a/lib/towerops/snmp/profiles/vendors/routeros.ex +++ b/lib/towerops/snmp/profiles/vendors/routeros.ex @@ -606,8 +606,8 @@ defmodule Towerops.Snmp.Profiles.Vendors.Routeros do end # Map mtxrGaugeUnit value to sensor type, unit string, and divisor - # Based on LibreNMS routeros.yaml - temperature is in whole degrees, voltage/current/power in deci-units - defp gauge_unit_to_sensor_type(@gauge_unit_celsius), do: {"temperature", "°C", 1} + # Mikrotik reports temperature in tenths of degrees (e.g., 230 = 23.0°C) + defp gauge_unit_to_sensor_type(@gauge_unit_celsius), do: {"temperature", "°C", 10} defp gauge_unit_to_sensor_type(@gauge_unit_rpm), do: {"fanspeed", "RPM", 1} defp gauge_unit_to_sensor_type(@gauge_unit_dv), do: {"voltage", "V", 10} defp gauge_unit_to_sensor_type(@gauge_unit_da), do: {"current", "A", 10} @@ -646,7 +646,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.Routeros do # Sensor type configurations for overrides (must match gauge_unit_to_sensor_type divisors) defp sensor_type_config("voltage"), do: {"voltage", "V", 10} - defp sensor_type_config("temperature"), do: {"temperature", "°C", 1} + defp sensor_type_config("temperature"), do: {"temperature", "°C", 10} defp sensor_type_config("current"), do: {"current", "A", 10} defp sensor_type_config("power"), do: {"power", "W", 10} defp sensor_type_config("fanspeed"), do: {"fanspeed", "RPM", 1} diff --git a/priv/repo/migrations/20260131181404_fix_mikrotik_temperature_sensor_divisor.exs b/priv/repo/migrations/20260131181404_fix_mikrotik_temperature_sensor_divisor.exs new file mode 100644 index 00000000..e29632d1 --- /dev/null +++ b/priv/repo/migrations/20260131181404_fix_mikrotik_temperature_sensor_divisor.exs @@ -0,0 +1,36 @@ +defmodule Towerops.Repo.Migrations.FixMikrotikTemperatureSensorDivisor do + use Ecto.Migration + + def up do + # Update Mikrotik temperature sensors (from gauge table) to use divisor 10 + # Mikrotik reports temperature in tenths of degrees (e.g., 230 = 23.0°C) + # Match by OID pattern: 1.3.6.1.4.1.14988.1.1.3.100.1.3.* (gauge table) + execute """ + UPDATE snmp_sensors + SET sensor_divisor = 10 + WHERE sensor_type = 'temperature' + AND ( + sensor_index LIKE 'mikrotik_gauge_%' + OR sensor_oid LIKE '1.3.6.1.4.1.14988.1.1.3.100.1.3.%' + ) + AND sensor_divisor = 1 + """ + + # Note: Optical table sensors (1.3.6.1.4.1.14988.1.1.19.1.1.6.*) + # correctly use divisor 1 and are not affected by this migration + end + + def down do + # Revert to divisor 1 (incorrect, but reversible) + execute """ + UPDATE snmp_sensors + SET sensor_divisor = 1 + WHERE sensor_type = 'temperature' + AND ( + sensor_index LIKE 'mikrotik_gauge_%' + OR sensor_oid LIKE '1.3.6.1.4.1.14988.1.1.3.100.1.3.%' + ) + AND sensor_divisor = 10 + """ + end +end diff --git a/test/towerops/snmp/profiles/vendors/routeros_test.exs b/test/towerops/snmp/profiles/vendors/routeros_test.exs index b6158ffa..fb69e2dc 100644 --- a/test/towerops/snmp/profiles/vendors/routeros_test.exs +++ b/test/towerops/snmp/profiles/vendors/routeros_test.exs @@ -283,10 +283,10 @@ defmodule Towerops.Snmp.Profiles.Vendors.RouterosTest do %{oid: "#{@gauge_table}.2.1", value: "psu-voltage"}, %{oid: "#{@gauge_table}.3.1", value: 469}, %{oid: "#{@gauge_table}.4.1", value: 3}, - # CPU Temperature: raw value 45, unit type 1 (celsius) -> should be 45°C - # LibreNMS shows Mikrotik temperature values are in whole degrees, not deci-degrees + # CPU Temperature: raw value 450, unit type 1 (celsius) -> should be 45.0°C + # Mikrotik reports temperature in tenths of degrees (divisor 10) %{oid: "#{@gauge_table}.2.2", value: "cpu-temperature"}, - %{oid: "#{@gauge_table}.3.2", value: 45}, + %{oid: "#{@gauge_table}.3.2", value: 450}, %{oid: "#{@gauge_table}.4.2", value: 1} ]} end) @@ -305,12 +305,12 @@ defmodule Towerops.Snmp.Profiles.Vendors.RouterosTest do assert voltage_sensor.last_value == 46.9 # Find the temperature sensor - # LibreNMS shows Mikrotik temperature values are in whole degrees (divisor 1) + # Mikrotik reports temperature in tenths of degrees (e.g., 450 = 45.0°C) temp_sensor = Enum.find(sensors, &(&1.sensor_descr == "cpu-temperature")) assert temp_sensor assert temp_sensor.sensor_type == "temperature" assert temp_sensor.sensor_unit == "°C" - assert temp_sensor.sensor_divisor == 1 + assert temp_sensor.sensor_divisor == 10 assert temp_sensor.last_value == 45.0 end