feat(snmp): add 6 new vendor modules (cnwave60, cnmatrix, ruckus_sz, deliberant, engenius, grandstream)

This commit is contained in:
Graham McIntire 2026-01-22 09:53:33 -06:00
parent 7c2014842d
commit e1bc56e065
No known key found for this signature in database
16 changed files with 1191 additions and 7 deletions

View file

@ -0,0 +1,87 @@
defmodule Towerops.Snmp.Profiles.Vendors.Cnmatrix do
@moduledoc """
Cambium cnMatrix device-specific SNMP handling.
Supports Cambium cnMatrix managed Ethernet switches.
Supported devices:
- cnMatrix EX1010
- cnMatrix EX1028
- cnMatrix EX2010
- cnMatrix EX2028
- cnMatrix TX1012
- cnMatrix TX2012
"""
@behaviour Towerops.Snmp.Profiles.Vendors.Vendor
alias Towerops.Snmp.Client
alias Towerops.Snmp.Profiles.Vendors.Vendor
# Cambium cnMatrix Enterprise OID: 1.3.6.1.4.1.17713.24
@model_oid "1.3.6.1.4.1.17713.24.1.1.1.0"
@impl true
def profile_names do
["cnmatrix"]
end
@impl true
def detect_hardware(client_opts) do
case Client.get(client_opts, @model_oid) do
{:ok, model} when is_binary(model) -> model
_ -> nil
end
end
@impl true
def discover_wireless_sensors(client_opts) do
Vendor.fetch_sensors(wireless_oid_defs(), client_opts)
end
@impl true
def wireless_oid_defs do
[
# CPU Utilization
%{
oid: "1.3.6.1.4.1.17713.24.2.1.0",
sensor_type: "load",
sensor_descr: "CPU Utilization",
sensor_unit: "%",
sensor_divisor: 1
},
# Memory Utilization
%{
oid: "1.3.6.1.4.1.17713.24.2.2.0",
sensor_type: "load",
sensor_descr: "Memory Utilization",
sensor_unit: "%",
sensor_divisor: 1
},
# System Temperature
%{
oid: "1.3.6.1.4.1.17713.24.3.1.0",
sensor_type: "temperature",
sensor_descr: "System Temperature",
sensor_unit: "C",
sensor_divisor: 1
},
# Fan Speed
%{
oid: "1.3.6.1.4.1.17713.24.3.2.0",
sensor_type: "fanspeed",
sensor_descr: "Fan Speed",
sensor_unit: "RPM",
sensor_divisor: 1
},
# Total PoE Power
%{
oid: "1.3.6.1.4.1.17713.24.4.1.0",
sensor_type: "power",
sensor_descr: "Total PoE Power",
sensor_unit: "W",
sensor_divisor: 1000
}
]
end
end

View file

@ -0,0 +1,85 @@
defmodule Towerops.Snmp.Profiles.Vendors.Cnwave60 do
@moduledoc """
Cambium cnWave 60GHz device-specific SNMP handling.
Supports Cambium cnWave 60GHz fixed wireless equipment.
Supported devices:
- cnWave V1000
- cnWave V3000
- cnWave V5000
- cnWave E500/E600
"""
@behaviour Towerops.Snmp.Profiles.Vendors.Vendor
alias Towerops.Snmp.Client
alias Towerops.Snmp.Profiles.Vendors.Vendor
# Cambium cnWave 60 Enterprise OID: 1.3.6.1.4.1.17713.60
@model_oid "1.3.6.1.4.1.17713.60.1.1.1.0"
@impl true
def profile_names do
["cnwave60"]
end
@impl true
def detect_hardware(client_opts) do
case Client.get(client_opts, @model_oid) do
{:ok, model} when is_binary(model) -> model
_ -> nil
end
end
@impl true
def discover_wireless_sensors(client_opts) do
Vendor.fetch_sensors(wireless_oid_defs(), client_opts)
end
@impl true
def wireless_oid_defs do
[
# Receive Signal Level (RSL)
%{
oid: "1.3.6.1.4.1.17713.60.12.1.0",
sensor_type: "rssi",
sensor_descr: "Receive Signal Level",
sensor_unit: "dBm",
sensor_divisor: 10
},
# Transmit Power
%{
oid: "1.3.6.1.4.1.17713.60.12.2.0",
sensor_type: "power",
sensor_descr: "Transmit Power",
sensor_unit: "dBm",
sensor_divisor: 10
},
# Signal to Noise Ratio
%{
oid: "1.3.6.1.4.1.17713.60.12.3.0",
sensor_type: "snr",
sensor_descr: "Signal to Noise Ratio",
sensor_unit: "dB",
sensor_divisor: 10
},
# Link Capacity
%{
oid: "1.3.6.1.4.1.17713.60.12.4.0",
sensor_type: "capacity",
sensor_descr: "Link Capacity",
sensor_unit: "Mbps",
sensor_divisor: 1
},
# System Temperature
%{
oid: "1.3.6.1.4.1.17713.60.13.1.0",
sensor_type: "temperature",
sensor_descr: "System Temperature",
sensor_unit: "C",
sensor_divisor: 1
}
]
end
end

View file

@ -0,0 +1,85 @@
defmodule Towerops.Snmp.Profiles.Vendors.Deliberant do
@moduledoc """
Deliberant (LigoWave) device-specific SNMP handling.
Supports Deliberant/LigoWave wireless equipment.
Supported devices:
- DLB APC Series
- DLB APC 5M
- DLB APC 2M
- LigoPTP RapidFire
"""
@behaviour Towerops.Snmp.Profiles.Vendors.Vendor
alias Towerops.Snmp.Client
alias Towerops.Snmp.Profiles.Vendors.Vendor
# Deliberant/LigoWave Enterprise OID: 1.3.6.1.4.1.32761
@model_oid "1.3.6.1.4.1.32761.1.1.1.0"
@impl true
def profile_names do
["deliberant"]
end
@impl true
def detect_hardware(client_opts) do
case Client.get(client_opts, @model_oid) do
{:ok, model} when is_binary(model) -> model
_ -> nil
end
end
@impl true
def discover_wireless_sensors(client_opts) do
Vendor.fetch_sensors(wireless_oid_defs(), client_opts)
end
@impl true
def wireless_oid_defs do
[
# Receive Signal Level
%{
oid: "1.3.6.1.4.1.32761.3.5.1.2.1.6.1",
sensor_type: "rssi",
sensor_descr: "Signal Level",
sensor_unit: "dBm",
sensor_divisor: 1
},
# Noise Floor
%{
oid: "1.3.6.1.4.1.32761.3.5.1.2.1.7.1",
sensor_type: "noise",
sensor_descr: "Noise Floor",
sensor_unit: "dBm",
sensor_divisor: 1
},
# Transmit CCQ
%{
oid: "1.3.6.1.4.1.32761.3.5.1.2.1.8.1",
sensor_type: "quality",
sensor_descr: "Transmit CCQ",
sensor_unit: "%",
sensor_divisor: 1
},
# Connected Clients
%{
oid: "1.3.6.1.4.1.32761.3.5.1.2.1.9.1",
sensor_type: "clients",
sensor_descr: "Connected Clients",
sensor_unit: "",
sensor_divisor: 1
},
# CPU Temperature
%{
oid: "1.3.6.1.4.1.32761.3.1.1.2.0",
sensor_type: "temperature",
sensor_descr: "CPU Temperature",
sensor_unit: "C",
sensor_divisor: 1
}
]
end
end

View file

@ -0,0 +1,102 @@
defmodule Towerops.Snmp.Profiles.Vendors.Engenius do
@moduledoc """
EnGenius device-specific SNMP handling.
Supports EnGenius wireless access points and outdoor equipment.
Supported devices:
- ENS Series (ENS500, ENS620EXT)
- EWS Series (EWS357AP, EWS377AP)
- ECW Series (ECW230, ECW260)
- EnStationAC
- EnJet Series
"""
@behaviour Towerops.Snmp.Profiles.Vendors.Vendor
alias Towerops.Snmp.Client
alias Towerops.Snmp.Profiles.Vendors.Vendor
# EnGenius Enterprise OID: 1.3.6.1.4.1.14125
@model_oid "1.3.6.1.4.1.14125.1.1.1.0"
@impl true
def profile_names do
["engenius"]
end
@impl true
def detect_hardware(client_opts) do
case Client.get(client_opts, @model_oid) do
{:ok, model} when is_binary(model) -> model
_ -> nil
end
end
@impl true
def discover_wireless_sensors(client_opts) do
Vendor.fetch_sensors(wireless_oid_defs(), client_opts)
end
@impl true
def wireless_oid_defs do
[
# Total Connected Clients
%{
oid: "1.3.6.1.4.1.14125.100.1.4.1.0",
sensor_type: "clients",
sensor_descr: "Connected Clients",
sensor_unit: "",
sensor_divisor: 1
},
# 2.4GHz Clients
%{
oid: "1.3.6.1.4.1.14125.100.1.4.2.0",
sensor_type: "clients",
sensor_descr: "2.4GHz Clients",
sensor_unit: "",
sensor_divisor: 1
},
# 5GHz Clients
%{
oid: "1.3.6.1.4.1.14125.100.1.4.3.0",
sensor_type: "clients",
sensor_descr: "5GHz Clients",
sensor_unit: "",
sensor_divisor: 1
},
# CPU Utilization
%{
oid: "1.3.6.1.4.1.14125.100.1.5.1.0",
sensor_type: "load",
sensor_descr: "CPU Utilization",
sensor_unit: "%",
sensor_divisor: 1
},
# Memory Utilization
%{
oid: "1.3.6.1.4.1.14125.100.1.5.2.0",
sensor_type: "load",
sensor_descr: "Memory Utilization",
sensor_unit: "%",
sensor_divisor: 1
},
# Channel Utilization 2.4GHz
%{
oid: "1.3.6.1.4.1.14125.100.1.6.1.0",
sensor_type: "load",
sensor_descr: "2.4GHz Channel Utilization",
sensor_unit: "%",
sensor_divisor: 1
},
# Channel Utilization 5GHz
%{
oid: "1.3.6.1.4.1.14125.100.1.6.2.0",
sensor_type: "load",
sensor_descr: "5GHz Channel Utilization",
sensor_unit: "%",
sensor_divisor: 1
}
]
end
end

View file

@ -0,0 +1,86 @@
defmodule Towerops.Snmp.Profiles.Vendors.Grandstream do
@moduledoc """
Grandstream device-specific SNMP handling.
Supports Grandstream wireless access points.
Supported devices:
- GWN7600 Series
- GWN7610
- GWN7615
- GWN7660
- GWN7664
"""
@behaviour Towerops.Snmp.Profiles.Vendors.Vendor
alias Towerops.Snmp.Client
alias Towerops.Snmp.Profiles.Vendors.Vendor
# Grandstream Enterprise OID: 1.3.6.1.4.1.42397
@model_oid "1.3.6.1.4.1.42397.1.1.2.1.0"
@impl true
def profile_names do
["grandstream-ap"]
end
@impl true
def detect_hardware(client_opts) do
case Client.get(client_opts, @model_oid) do
{:ok, model} when is_binary(model) -> model
_ -> nil
end
end
@impl true
def discover_wireless_sensors(client_opts) do
Vendor.fetch_sensors(wireless_oid_defs(), client_opts)
end
@impl true
def wireless_oid_defs do
[
# Total Connected Clients
%{
oid: "1.3.6.1.4.1.42397.1.1.3.1.0",
sensor_type: "clients",
sensor_descr: "Connected Clients",
sensor_unit: "",
sensor_divisor: 1
},
# 2.4GHz Clients
%{
oid: "1.3.6.1.4.1.42397.1.1.3.2.0",
sensor_type: "clients",
sensor_descr: "2.4GHz Clients",
sensor_unit: "",
sensor_divisor: 1
},
# 5GHz Clients
%{
oid: "1.3.6.1.4.1.42397.1.1.3.3.0",
sensor_type: "clients",
sensor_descr: "5GHz Clients",
sensor_unit: "",
sensor_divisor: 1
},
# CPU Utilization
%{
oid: "1.3.6.1.4.1.42397.1.1.4.1.0",
sensor_type: "load",
sensor_descr: "CPU Utilization",
sensor_unit: "%",
sensor_divisor: 1
},
# Memory Utilization
%{
oid: "1.3.6.1.4.1.42397.1.1.4.2.0",
sensor_type: "load",
sensor_descr: "Memory Utilization",
sensor_unit: "%",
sensor_divisor: 1
}
]
end
end

View file

@ -7,7 +7,6 @@ defmodule Towerops.Snmp.Profiles.Vendors.Ligoos do
Supported devices:
- LigoWave LigoPTP series
- LigoWave DLB series
- Deliberant devices (share same firmware)
"""
@behaviour Towerops.Snmp.Profiles.Vendors.Vendor
@ -19,7 +18,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.Ligoos do
@wl_if_table "1.3.6.1.4.1.32750.3.10.1.2.1.1"
@impl true
def profile_names, do: ["ligoos", "deliberant"]
def profile_names, do: ["ligoos"]
@impl true
def detect_hardware(_client_opts) do

View file

@ -16,10 +16,15 @@ defmodule Towerops.Snmp.Profiles.Vendors.Registry do
alias Towerops.Snmp.Profiles.Vendors.CambiumPtp
alias Towerops.Snmp.Profiles.Vendors.Ciscowap
alias Towerops.Snmp.Profiles.Vendors.Ciscowlc
alias Towerops.Snmp.Profiles.Vendors.Cnmatrix
alias Towerops.Snmp.Profiles.Vendors.Cnpilot
alias Towerops.Snmp.Profiles.Vendors.Cnwave60
alias Towerops.Snmp.Profiles.Vendors.Deliberant
alias Towerops.Snmp.Profiles.Vendors.Dragonwave
alias Towerops.Snmp.Profiles.Vendors.Engenius
alias Towerops.Snmp.Profiles.Vendors.Epmp
alias Towerops.Snmp.Profiles.Vendors.Exalt
alias Towerops.Snmp.Profiles.Vendors.Grandstream
alias Towerops.Snmp.Profiles.Vendors.Ligoos
alias Towerops.Snmp.Profiles.Vendors.Mimosa
alias Towerops.Snmp.Profiles.Vendors.Netonix
@ -28,6 +33,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.Registry do
alias Towerops.Snmp.Profiles.Vendors.Radwin
alias Towerops.Snmp.Profiles.Vendors.Routeros
alias Towerops.Snmp.Profiles.Vendors.Ruckus
alias Towerops.Snmp.Profiles.Vendors.RuckusSz
alias Towerops.Snmp.Profiles.Vendors.Saf
alias Towerops.Snmp.Profiles.Vendors.Siae
alias Towerops.Snmp.Profiles.Vendors.Siklu
@ -37,18 +43,23 @@ defmodule Towerops.Snmp.Profiles.Vendors.Registry do
@vendors [
Aerohive,
Airos,
Airfiber,
Airos,
Aruba,
Aviat,
Baicells,
CambiumPtp,
Ciscowap,
Ciscowlc,
Cnmatrix,
Cnpilot,
Cnwave60,
Deliberant,
Dragonwave,
Engenius,
Epmp,
Exalt,
Grandstream,
Ligoos,
Mimosa,
Netonix,
@ -57,6 +68,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.Registry do
Radwin,
Routeros,
Ruckus,
RuckusSz,
Saf,
Siae,
Siklu,

View file

@ -0,0 +1,85 @@
defmodule Towerops.Snmp.Profiles.Vendors.RuckusSz do
@moduledoc """
Ruckus SmartZone wireless controller device-specific SNMP handling.
Supports Ruckus SmartZone wireless LAN controllers.
Supported devices:
- SmartZone 100 (SZ-100)
- SmartZone 144 (SZ-144)
- SmartZone 300 (SZ-300)
- Virtual SmartZone (vSZ)
"""
@behaviour Towerops.Snmp.Profiles.Vendors.Vendor
alias Towerops.Snmp.Client
alias Towerops.Snmp.Profiles.Vendors.Vendor
# Ruckus Enterprise OID: 1.3.6.1.4.1.25053
@model_oid "1.3.6.1.4.1.25053.1.1.1.0"
@impl true
def profile_names do
["ruckuswireless-sz"]
end
@impl true
def detect_hardware(client_opts) do
case Client.get(client_opts, @model_oid) do
{:ok, model} when is_binary(model) -> model
_ -> nil
end
end
@impl true
def discover_wireless_sensors(client_opts) do
Vendor.fetch_sensors(wireless_oid_defs(), client_opts)
end
@impl true
def wireless_oid_defs do
[
# Total Access Points
%{
oid: "1.3.6.1.4.1.25053.1.2.1.1.1.1.1.0",
sensor_type: "count",
sensor_descr: "Total Access Points",
sensor_unit: "",
sensor_divisor: 1
},
# Connected Access Points
%{
oid: "1.3.6.1.4.1.25053.1.2.1.1.1.1.2.0",
sensor_type: "count",
sensor_descr: "Connected Access Points",
sensor_unit: "",
sensor_divisor: 1
},
# Total Wireless Clients
%{
oid: "1.3.6.1.4.1.25053.1.2.1.1.1.1.3.0",
sensor_type: "clients",
sensor_descr: "Total Wireless Clients",
sensor_unit: "",
sensor_divisor: 1
},
# CPU Utilization
%{
oid: "1.3.6.1.4.1.25053.1.2.1.1.1.2.1.0",
sensor_type: "load",
sensor_descr: "CPU Utilization",
sensor_unit: "%",
sensor_divisor: 1
},
# Memory Utilization
%{
oid: "1.3.6.1.4.1.25053.1.2.1.1.1.2.2.0",
sensor_type: "load",
sensor_descr: "Memory Utilization",
sensor_unit: "%",
sensor_divisor: 1
}
]
end
end

View file

@ -0,0 +1,106 @@
defmodule Towerops.Snmp.Profiles.Vendors.CnmatrixTest do
use Towerops.DataCase, async: true
import Mox
alias Towerops.Snmp.Profiles.Vendors.Cnmatrix
alias Towerops.Snmp.SnmpMock
setup :verify_on_exit!
@client_opts [
ip: "192.168.1.1",
community: "public",
version: "2c",
port: 161,
timeout: 5000
]
describe "profile_names/0" do
test "returns cnmatrix profile name" do
assert Cnmatrix.profile_names() == ["cnmatrix"]
end
end
describe "detect_hardware/1" do
test "detects hardware from model OID" do
expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.24.1.1.1.0", _ ->
{:ok, "cnMatrix EX2028"}
end)
assert Cnmatrix.detect_hardware(@client_opts) == "cnMatrix EX2028"
end
test "returns nil when OID unavailable" do
expect(SnmpMock, :get, fn _, _, _ ->
{:error, :no_such_object}
end)
assert Cnmatrix.detect_hardware(@client_opts) == nil
end
end
describe "wireless_oid_defs/0" do
test "returns list of sensor definitions" do
defs = Cnmatrix.wireless_oid_defs()
assert is_list(defs)
assert [_ | _] = defs
end
test "includes CPU utilization sensor" do
defs = Cnmatrix.wireless_oid_defs()
cpu = Enum.find(defs, &(&1.sensor_descr == "CPU Utilization"))
assert cpu
assert cpu.sensor_type == "load"
assert cpu.sensor_unit == "%"
end
test "includes temperature sensor" do
defs = Cnmatrix.wireless_oid_defs()
temp = Enum.find(defs, &(&1.sensor_type == "temperature"))
assert temp
assert temp.sensor_descr == "System Temperature"
end
test "includes PoE power sensor" do
defs = Cnmatrix.wireless_oid_defs()
poe = Enum.find(defs, &(&1.sensor_descr == "Total PoE Power"))
assert poe
assert poe.sensor_type == "power"
end
end
describe "discover_wireless_sensors/1" do
test "discovers sensors when SNMP responds" do
expect(SnmpMock, :get, 5, fn _, oid, _ ->
cond do
String.contains?(oid, "17713.24.2.1.0") -> {:ok, 35}
String.contains?(oid, "17713.24.2.2.0") -> {:ok, 68}
String.contains?(oid, "17713.24.3.1.0") -> {:ok, 42}
String.contains?(oid, "17713.24.3.2.0") -> {:ok, 3500}
String.contains?(oid, "17713.24.4.1.0") -> {:ok, 75_000}
true -> {:error, :no_such_object}
end
end)
sensors = Cnmatrix.discover_wireless_sensors(@client_opts)
assert is_list(sensors)
assert length(sensors) == 5
end
test "returns empty list when no sensors respond" do
expect(SnmpMock, :get, 5, fn _, _, _ ->
{:error, :no_such_object}
end)
sensors = Cnmatrix.discover_wireless_sensors(@client_opts)
assert sensors == []
end
end
end

View file

@ -0,0 +1,106 @@
defmodule Towerops.Snmp.Profiles.Vendors.Cnwave60Test do
use Towerops.DataCase, async: true
import Mox
alias Towerops.Snmp.Profiles.Vendors.Cnwave60
alias Towerops.Snmp.SnmpMock
setup :verify_on_exit!
@client_opts [
ip: "192.168.1.1",
community: "public",
version: "2c",
port: 161,
timeout: 5000
]
describe "profile_names/0" do
test "returns cnwave60 profile name" do
assert Cnwave60.profile_names() == ["cnwave60"]
end
end
describe "detect_hardware/1" do
test "detects hardware from model OID" do
expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.17713.60.1.1.1.0", _ ->
{:ok, "cnWave V3000"}
end)
assert Cnwave60.detect_hardware(@client_opts) == "cnWave V3000"
end
test "returns nil when OID unavailable" do
expect(SnmpMock, :get, fn _, _, _ ->
{:error, :no_such_object}
end)
assert Cnwave60.detect_hardware(@client_opts) == nil
end
end
describe "wireless_oid_defs/0" do
test "returns list of wireless sensor definitions" do
defs = Cnwave60.wireless_oid_defs()
assert is_list(defs)
assert [_ | _] = defs
end
test "includes receive signal level sensor" do
defs = Cnwave60.wireless_oid_defs()
rsl = Enum.find(defs, &(&1.sensor_descr == "Receive Signal Level"))
assert rsl
assert rsl.sensor_type == "rssi"
assert rsl.sensor_divisor == 10
end
test "includes SNR sensor" do
defs = Cnwave60.wireless_oid_defs()
snr = Enum.find(defs, &(&1.sensor_descr == "Signal to Noise Ratio"))
assert snr
assert snr.sensor_type == "snr"
end
test "includes temperature sensor" do
defs = Cnwave60.wireless_oid_defs()
temp = Enum.find(defs, &(&1.sensor_type == "temperature"))
assert temp
assert temp.sensor_descr == "System Temperature"
end
end
describe "discover_wireless_sensors/1" do
test "discovers sensors when SNMP responds" do
expect(SnmpMock, :get, 5, fn _, oid, _ ->
cond do
String.contains?(oid, "17713.60.12.1.0") -> {:ok, -550}
String.contains?(oid, "17713.60.12.2.0") -> {:ok, 200}
String.contains?(oid, "17713.60.12.3.0") -> {:ok, 280}
String.contains?(oid, "17713.60.12.4.0") -> {:ok, 1000}
String.contains?(oid, "17713.60.13.1.0") -> {:ok, 45}
true -> {:error, :no_such_object}
end
end)
sensors = Cnwave60.discover_wireless_sensors(@client_opts)
assert is_list(sensors)
assert length(sensors) == 5
end
test "returns empty list when no sensors respond" do
expect(SnmpMock, :get, 5, fn _, _, _ ->
{:error, :no_such_object}
end)
sensors = Cnwave60.discover_wireless_sensors(@client_opts)
assert sensors == []
end
end
end

View file

@ -0,0 +1,106 @@
defmodule Towerops.Snmp.Profiles.Vendors.DeliberantTest do
use Towerops.DataCase, async: true
import Mox
alias Towerops.Snmp.Profiles.Vendors.Deliberant
alias Towerops.Snmp.SnmpMock
setup :verify_on_exit!
@client_opts [
ip: "192.168.1.1",
community: "public",
version: "2c",
port: 161,
timeout: 5000
]
describe "profile_names/0" do
test "returns deliberant profile name" do
assert Deliberant.profile_names() == ["deliberant"]
end
end
describe "detect_hardware/1" do
test "detects hardware from model OID" do
expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.32761.1.1.1.0", _ ->
{:ok, "DLB APC 5M"}
end)
assert Deliberant.detect_hardware(@client_opts) == "DLB APC 5M"
end
test "returns nil when OID unavailable" do
expect(SnmpMock, :get, fn _, _, _ ->
{:error, :no_such_object}
end)
assert Deliberant.detect_hardware(@client_opts) == nil
end
end
describe "wireless_oid_defs/0" do
test "returns list of wireless sensor definitions" do
defs = Deliberant.wireless_oid_defs()
assert is_list(defs)
assert [_ | _] = defs
end
test "includes signal level sensor" do
defs = Deliberant.wireless_oid_defs()
signal = Enum.find(defs, &(&1.sensor_descr == "Signal Level"))
assert signal
assert signal.sensor_type == "rssi"
assert signal.sensor_unit == "dBm"
end
test "includes noise floor sensor" do
defs = Deliberant.wireless_oid_defs()
noise = Enum.find(defs, &(&1.sensor_descr == "Noise Floor"))
assert noise
assert noise.sensor_type == "noise"
end
test "includes temperature sensor" do
defs = Deliberant.wireless_oid_defs()
temp = Enum.find(defs, &(&1.sensor_type == "temperature"))
assert temp
assert temp.sensor_descr == "CPU Temperature"
end
end
describe "discover_wireless_sensors/1" do
test "discovers sensors when SNMP responds" do
expect(SnmpMock, :get, 5, fn _, oid, _ ->
cond do
String.contains?(oid, "32761.3.5.1.2.1.6.1") -> {:ok, -65}
String.contains?(oid, "32761.3.5.1.2.1.7.1") -> {:ok, -95}
String.contains?(oid, "32761.3.5.1.2.1.8.1") -> {:ok, 85}
String.contains?(oid, "32761.3.5.1.2.1.9.1") -> {:ok, 12}
String.contains?(oid, "32761.3.1.1.2.0") -> {:ok, 55}
true -> {:error, :no_such_object}
end
end)
sensors = Deliberant.discover_wireless_sensors(@client_opts)
assert is_list(sensors)
assert length(sensors) == 5
end
test "returns empty list when no sensors respond" do
expect(SnmpMock, :get, 5, fn _, _, _ ->
{:error, :no_such_object}
end)
sensors = Deliberant.discover_wireless_sensors(@client_opts)
assert sensors == []
end
end
end

View file

@ -0,0 +1,110 @@
defmodule Towerops.Snmp.Profiles.Vendors.EngeniusTest do
use Towerops.DataCase, async: true
import Mox
alias Towerops.Snmp.Profiles.Vendors.Engenius
alias Towerops.Snmp.SnmpMock
setup :verify_on_exit!
@client_opts [
ip: "192.168.1.1",
community: "public",
version: "2c",
port: 161,
timeout: 5000
]
describe "profile_names/0" do
test "returns engenius profile name" do
assert Engenius.profile_names() == ["engenius"]
end
end
describe "detect_hardware/1" do
test "detects hardware from model OID" do
expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.14125.1.1.1.0", _ ->
{:ok, "EWS377AP"}
end)
assert Engenius.detect_hardware(@client_opts) == "EWS377AP"
end
test "returns nil when OID unavailable" do
expect(SnmpMock, :get, fn _, _, _ ->
{:error, :no_such_object}
end)
assert Engenius.detect_hardware(@client_opts) == nil
end
end
describe "wireless_oid_defs/0" do
test "returns list of wireless sensor definitions" do
defs = Engenius.wireless_oid_defs()
assert is_list(defs)
assert [_ | _] = defs
end
test "includes total client count sensor" do
defs = Engenius.wireless_oid_defs()
clients = Enum.find(defs, &(&1.sensor_descr == "Connected Clients"))
assert clients
assert clients.sensor_type == "clients"
end
test "includes band-specific client sensors" do
defs = Engenius.wireless_oid_defs()
clients_2g = Enum.find(defs, &(&1.sensor_descr == "2.4GHz Clients"))
clients_5g = Enum.find(defs, &(&1.sensor_descr == "5GHz Clients"))
assert clients_2g
assert clients_5g
end
test "includes channel utilization sensors" do
defs = Engenius.wireless_oid_defs()
util_2g = Enum.find(defs, &(&1.sensor_descr == "2.4GHz Channel Utilization"))
util_5g = Enum.find(defs, &(&1.sensor_descr == "5GHz Channel Utilization"))
assert util_2g
assert util_2g.sensor_type == "load"
assert util_5g
end
end
describe "discover_wireless_sensors/1" do
test "discovers sensors when SNMP responds" do
expect(SnmpMock, :get, 7, fn _, oid, _ ->
cond do
String.contains?(oid, "14125.100.1.4.1.0") -> {:ok, 45}
String.contains?(oid, "14125.100.1.4.2.0") -> {:ok, 20}
String.contains?(oid, "14125.100.1.4.3.0") -> {:ok, 25}
String.contains?(oid, "14125.100.1.5.1.0") -> {:ok, 35}
String.contains?(oid, "14125.100.1.5.2.0") -> {:ok, 68}
String.contains?(oid, "14125.100.1.6.1.0") -> {:ok, 45}
String.contains?(oid, "14125.100.1.6.2.0") -> {:ok, 30}
true -> {:error, :no_such_object}
end
end)
sensors = Engenius.discover_wireless_sensors(@client_opts)
assert is_list(sensors)
assert length(sensors) == 7
end
test "returns empty list when no sensors respond" do
expect(SnmpMock, :get, 7, fn _, _, _ ->
{:error, :no_such_object}
end)
sensors = Engenius.discover_wireless_sensors(@client_opts)
assert sensors == []
end
end
end

View file

@ -0,0 +1,109 @@
defmodule Towerops.Snmp.Profiles.Vendors.GrandstreamTest do
use Towerops.DataCase, async: true
import Mox
alias Towerops.Snmp.Profiles.Vendors.Grandstream
alias Towerops.Snmp.SnmpMock
setup :verify_on_exit!
@client_opts [
ip: "192.168.1.1",
community: "public",
version: "2c",
port: 161,
timeout: 5000
]
describe "profile_names/0" do
test "returns grandstream-ap profile name" do
assert Grandstream.profile_names() == ["grandstream-ap"]
end
end
describe "detect_hardware/1" do
test "detects hardware from model OID" do
expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.42397.1.1.2.1.0", _ ->
{:ok, "GWN7660"}
end)
assert Grandstream.detect_hardware(@client_opts) == "GWN7660"
end
test "returns nil when OID unavailable" do
expect(SnmpMock, :get, fn _, _, _ ->
{:error, :no_such_object}
end)
assert Grandstream.detect_hardware(@client_opts) == nil
end
end
describe "wireless_oid_defs/0" do
test "returns list of wireless sensor definitions" do
defs = Grandstream.wireless_oid_defs()
assert is_list(defs)
assert [_ | _] = defs
end
test "includes total client count sensor" do
defs = Grandstream.wireless_oid_defs()
clients = Enum.find(defs, &(&1.sensor_descr == "Connected Clients"))
assert clients
assert clients.sensor_type == "clients"
end
test "includes band-specific client sensors" do
defs = Grandstream.wireless_oid_defs()
clients_2g = Enum.find(defs, &(&1.sensor_descr == "2.4GHz Clients"))
clients_5g = Enum.find(defs, &(&1.sensor_descr == "5GHz Clients"))
assert clients_2g
assert clients_5g
end
test "includes CPU and memory sensors" do
defs = Grandstream.wireless_oid_defs()
cpu = Enum.find(defs, &(&1.sensor_descr == "CPU Utilization"))
mem = Enum.find(defs, &(&1.sensor_descr == "Memory Utilization"))
assert cpu
assert cpu.sensor_type == "load"
assert mem
assert mem.sensor_type == "load"
end
end
describe "discover_wireless_sensors/1" do
test "discovers sensors when SNMP responds" do
expect(SnmpMock, :get, 5, fn _, oid, _ ->
cond do
String.contains?(oid, "42397.1.1.3.1.0") -> {:ok, 45}
String.contains?(oid, "42397.1.1.3.2.0") -> {:ok, 20}
String.contains?(oid, "42397.1.1.3.3.0") -> {:ok, 25}
String.contains?(oid, "42397.1.1.4.1.0") -> {:ok, 35}
String.contains?(oid, "42397.1.1.4.2.0") -> {:ok, 68}
true -> {:error, :no_such_object}
end
end)
sensors = Grandstream.discover_wireless_sensors(@client_opts)
assert is_list(sensors)
assert length(sensors) == 5
end
test "returns empty list when no sensors respond" do
expect(SnmpMock, :get, 5, fn _, _, _ ->
{:error, :no_such_object}
end)
sensors = Grandstream.discover_wireless_sensors(@client_opts)
assert sensors == []
end
end
end

View file

@ -17,8 +17,8 @@ defmodule Towerops.Snmp.Profiles.Vendors.LigoosTest do
]
describe "profile_names/0" do
test "returns ligoos and deliberant profile names" do
assert Ligoos.profile_names() == ["ligoos", "deliberant"]
test "returns ligoos profile name" do
assert Ligoos.profile_names() == ["ligoos"]
end
end

View file

@ -6,6 +6,7 @@ defmodule Towerops.Snmp.Profiles.Vendors.RegistryTest do
alias Towerops.Snmp.Profiles.Vendors.Airfiber
alias Towerops.Snmp.Profiles.Vendors.Airos
alias Towerops.Snmp.Profiles.Vendors.Cnpilot
alias Towerops.Snmp.Profiles.Vendors.Deliberant
alias Towerops.Snmp.Profiles.Vendors.Dragonwave
alias Towerops.Snmp.Profiles.Vendors.Epmp
alias Towerops.Snmp.Profiles.Vendors.Exalt
@ -122,8 +123,8 @@ defmodule Towerops.Snmp.Profiles.Vendors.RegistryTest do
assert Registry.get_vendor("ligoos") == Ligoos
end
test "returns Ligoos for deliberant profile" do
assert Registry.get_vendor("deliberant") == Ligoos
test "returns Deliberant for deliberant profile" do
assert Registry.get_vendor("deliberant") == Deliberant
end
test "returns Cnpilot for cnpilot profile" do

View file

@ -0,0 +1,105 @@
defmodule Towerops.Snmp.Profiles.Vendors.RuckusSzTest do
use Towerops.DataCase, async: true
import Mox
alias Towerops.Snmp.Profiles.Vendors.RuckusSz
alias Towerops.Snmp.SnmpMock
setup :verify_on_exit!
@client_opts [
ip: "192.168.1.1",
community: "public",
version: "2c",
port: 161,
timeout: 5000
]
describe "profile_names/0" do
test "returns ruckuswireless-sz profile name" do
assert RuckusSz.profile_names() == ["ruckuswireless-sz"]
end
end
describe "detect_hardware/1" do
test "detects hardware from model OID" do
expect(SnmpMock, :get, fn _, "1.3.6.1.4.1.25053.1.1.1.0", _ ->
{:ok, "SmartZone 300"}
end)
assert RuckusSz.detect_hardware(@client_opts) == "SmartZone 300"
end
test "returns nil when OID unavailable" do
expect(SnmpMock, :get, fn _, _, _ ->
{:error, :no_such_object}
end)
assert RuckusSz.detect_hardware(@client_opts) == nil
end
end
describe "wireless_oid_defs/0" do
test "returns list of sensor definitions" do
defs = RuckusSz.wireless_oid_defs()
assert is_list(defs)
assert [_ | _] = defs
end
test "includes total APs sensor" do
defs = RuckusSz.wireless_oid_defs()
aps = Enum.find(defs, &(&1.sensor_descr == "Total Access Points"))
assert aps
assert aps.sensor_type == "count"
end
test "includes client count sensor" do
defs = RuckusSz.wireless_oid_defs()
clients = Enum.find(defs, &(&1.sensor_descr == "Total Wireless Clients"))
assert clients
assert clients.sensor_type == "clients"
end
test "includes CPU utilization sensor" do
defs = RuckusSz.wireless_oid_defs()
cpu = Enum.find(defs, &(&1.sensor_descr == "CPU Utilization"))
assert cpu
assert cpu.sensor_type == "load"
end
end
describe "discover_wireless_sensors/1" do
test "discovers sensors when SNMP responds" do
expect(SnmpMock, :get, 5, fn _, oid, _ ->
cond do
String.contains?(oid, "25053.1.2.1.1.1.1.1.0") -> {:ok, 150}
String.contains?(oid, "25053.1.2.1.1.1.1.2.0") -> {:ok, 145}
String.contains?(oid, "25053.1.2.1.1.1.1.3.0") -> {:ok, 2500}
String.contains?(oid, "25053.1.2.1.1.1.2.1.0") -> {:ok, 45}
String.contains?(oid, "25053.1.2.1.1.1.2.2.0") -> {:ok, 72}
true -> {:error, :no_such_object}
end
end)
sensors = RuckusSz.discover_wireless_sensors(@client_opts)
assert is_list(sensors)
assert length(sensors) == 5
end
test "returns empty list when no sensors respond" do
expect(SnmpMock, :get, 5, fn _, _, _ ->
{:error, :no_such_object}
end)
sensors = RuckusSz.discover_wireless_sensors(@client_opts)
assert sensors == []
end
end
end