towerops/lib/towerops/equipment.ex
Graham McIntire 3544d117a8
Implement SNMP polling for continuous data collection
Add background workers to regularly poll SNMP sensors and interfaces:

- Create PollerWorker GenServer to poll SNMP devices
- Poll all sensors for temperature, voltage, CPU, memory, etc.
- Poll all interfaces for bandwidth, errors, and discards
- Save time-series data to snmp_sensor_readings and snmp_interface_stats
- Integrate with monitoring supervisor to auto-start pollers
- Use same interval as connectivity checks (minimum 30 seconds)
- Add list_snmp_enabled_equipment function to Equipment context

Pollers start automatically on app boot for all SNMP-enabled equipment
and run independently of connectivity monitoring.
2026-01-04 12:56:51 -06:00

126 lines
2.8 KiB
Elixir

defmodule Towerops.Equipment do
@moduledoc """
The Equipment context.
"""
import Ecto.Query
alias Towerops.Equipment.Equipment, as: EquipmentSchema
alias Towerops.Repo
@doc """
Returns the list of equipment for a site.
"""
def list_site_equipment(site_id) do
Repo.all(from(e in EquipmentSchema, where: e.site_id == ^site_id, order_by: [asc: e.name]))
end
@doc """
Returns the list of all equipment for an organization (via sites).
"""
def list_organization_equipment(organization_id) do
Repo.all(
from(e in EquipmentSchema,
join: s in assoc(e, :site),
where: s.organization_id == ^organization_id,
order_by: [asc: e.name],
preload: [site: s]
)
)
end
@doc """
Returns the list of all equipment with monitoring enabled.
"""
def list_monitored_equipment do
Repo.all(
from(e in EquipmentSchema,
where: e.monitoring_enabled == true,
order_by: [asc: e.name]
)
)
end
@doc """
Returns the list of all equipment with SNMP enabled.
"""
def list_snmp_enabled_equipment do
Repo.all(
from(e in EquipmentSchema,
where: e.snmp_enabled == true,
order_by: [asc: e.name]
)
)
end
@doc """
Gets a single equipment.
"""
def get_equipment!(id) do
EquipmentSchema
|> Repo.get!(id)
|> Repo.preload([:site])
end
@doc """
Gets a single equipment belonging to a specific site.
"""
def get_site_equipment!(site_id, equipment_id) do
Repo.one!(from(e in EquipmentSchema, where: e.id == ^equipment_id, where: e.site_id == ^site_id, preload: [:site]))
end
@doc """
Creates equipment.
"""
def create_equipment(attrs) do
%EquipmentSchema{}
|> EquipmentSchema.changeset(attrs)
|> Repo.insert()
end
@doc """
Updates equipment.
"""
def update_equipment(%EquipmentSchema{} = equipment, attrs) do
equipment
|> EquipmentSchema.changeset(attrs)
|> Repo.update()
end
@doc """
Deletes equipment.
"""
def delete_equipment(%EquipmentSchema{} = equipment) do
Repo.delete(equipment)
end
@doc """
Returns an `%Ecto.Changeset{}` for tracking equipment changes.
"""
def change_equipment(%EquipmentSchema{} = equipment, attrs \\ %{}) do
EquipmentSchema.changeset(equipment, attrs)
end
@doc """
Updates the status of equipment.
"""
def update_equipment_status(%EquipmentSchema{} = equipment, new_status) do
now = DateTime.truncate(DateTime.utc_now(), :second)
changes = %{
status: new_status,
last_checked_at: now
}
changes =
if equipment.status == new_status do
changes
else
Map.put(changes, :last_status_change_at, now)
end
equipment
|> Ecto.Changeset.change(changes)
|> Repo.update()
end
end