Sets sensor_unit for all sensors that are missing it, fixing sensors
created before the discovery code was updated to set units properly.
Updates:
- Temperature sensors: set to '°C'
- Voltage sensors: set to 'V'
- Current sensors: set to 'mA'
- Power sensors: set to 'W'
- dBm sensors: set to 'dBm'
This ensures the device detail page displays units correctly for all
sensor types (e.g., "27 °C" instead of "27" for temperature).
The discovery code already sets these units for new sensors, so this
migration only affects existing data.
Related to:
- lib/towerops/snmp/profiles/vendors/routeros.ex:690 (°C)
- lib/towerops/snmp/profiles/vendors/routeros.ex:709 (V)
- lib/towerops/snmp/profiles/base.ex:1473-1480 (sensor_type_to_unit)
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Adds test case for the real-world scenario where MikroTik devices
report incorrect mtxrGaugeUnit values (e.g., reporting unit type 1
for celsius/temperature when the sensor is actually a voltage sensor).
This test verifies that the name-based override logic in
maybe_override_sensor_type/2 correctly handles this case:
- Sensor name: "psu1-voltage" or "psu2-voltage"
- Reported unit type: 1 (celsius/temperature)
- Expected result: voltage sensor with divisor 10
The override code was added in commit f402dcb (Jan 22, 2026) and
works correctly for new discoveries. Existing sensors created before
this date need the migration from commit 68a4ebf to fix their values.
Related: 20260125182836_fix_misclassified_mikrotik_voltage_sensors.exs
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixes voltage sensors that were incorrectly classified as temperature
sensors due to MikroTik devices reporting wrong mtxrGaugeUnit values.
Problem:
- Sensors with names like "psu1-voltage" and "psu2-voltage" were
classified as temperature sensors with divisor=1
- This caused voltage readings to display as 469V instead of 46.9V
- The RouterOS profile already has name-based override logic for new
discoveries, but existing sensors needed fixing
Solution:
- Migration identifies sensors by:
- OID pattern: 1.3.6.1.4.1.14988.1.1.3.100.1.3.%
- Type mismatch: sensor_type = 'temperature' but name contains 'voltage'
- Incorrect divisor: sensor_divisor = 1
- Updates sensor metadata: type, unit, divisor
- Corrects historical sensor_reading values by dividing by 10
Future discoveries are already protected by the name-based override
logic in lib/towerops/snmp/profiles/vendors/routeros.ex:620-630
🤖 Generated with Claude Code
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Mikrotik/RouterOS voltage sensors were showing incorrect values (469.0
instead of 46.9) because existing sensors in the database have
sensor_divisor=1 instead of the correct value of 10.
The RouterOS profile code was fixed in a previous commit to set
divisor=10 for new sensors, but existing sensors need to be updated.
Migration changes:
- Updates sensor_divisor from 1 to 10 for Mikrotik voltage sensors
- Identifies Mikrotik sensors by OID prefix: 1.3.6.1.4.1.14988.1.1.3.100.1.3
- Divides all historical sensor_reading values by 10 to correct the data
- Both up and down migrations included for full reversibility
After this migration:
- Voltage will show as 46.9V instead of 469.0V
- Historical graphs will show correct voltage values
Cloud pollers (is_cloud_poller = true, organization_id = nil) were
being blocked from polling devices because verify_device_organization
was checking if the device's organization matched the agent's
organization.
Since cloud pollers don't belong to any organization (organization_id
is nil), they should be allowed to poll devices from any organization.
Changes:
- verify_device_organization now allows access if organization_id is nil
- This fixes "Device not in agent's organization" errors for cloud pollers
Error before:
Device b7e8dd99-0b19-496d-97ae-9f2601d16464 not in agent's organization
Reverted k8s/Dockerfile back to using official hexpm/elixir and debian
images directly instead of custom gmcintire/towerops-base images.
This restores the original Dockerfile behavior where all dependencies
are installed during each build. The base image work in k8s/base-image/
remains available but is not used by the main application build.
Production was crashing with CaseClauseError when viewing device edit
form for devices using the global default cloud poller.
Added missing :global case branch to the agent source case statement
in form.html.heex line 127.
Displays: 'Using global default cloud poller: <agent_name>'