SNMP - Is anyone leveraging info via the Simple Network Management Protocol ?
-
Hi
In my ongoing quest to try and retrieve as much information as I can about the amount of energy I’m using , I found out that I could use SNMP to see how much power (watts) my UPS is handling .
To do this, I installed snmpd/snmp on my Vera linked Raspberry Pi, and then ran the following command.
local command = io.popen("ssh -i /etc/dropbear/dropbear_rsa_host_key pi@192.168.102.37 'snmpwalk -Os -c public -v 1 10.10.10.103' 2>&1") local response = command:read("*a") print(response)
Which returned a huge amount of information, which prompted me to ask the community here if there anything on Vera/OpenLuup that people have that can process this sort of information into a new devices and associated variables to then monitor/track going forward ?
iso.3.6.1.2.1.1.1.0 = STRING: "Eaton 5P 1150" iso.3.6.1.2.1.1.2.0 = OID: iso.3.6.1.4.1.705.1 iso.3.6.1.2.1.1.3.0 = Timeticks: (51435090) 5 days, 22:52:30.90 iso.3.6.1.2.1.1.4.0 = STRING: "Computer Room Manager" iso.3.6.1.2.1.1.5.0 = STRING: "ups239" iso.3.6.1.2.1.1.6.0 = STRING: "Computer Room" iso.3.6.1.2.1.1.7.0 = INTEGER: 72 iso.3.6.1.2.1.1.8.0 = Timeticks: (0) 0:00:00.00 iso.3.6.1.2.1.1.9.1.2.1 = OID: iso.3.6.1.6.3.1 iso.3.6.1.2.1.1.9.1.2.2 = OID: iso.3.6.1.6.3.10.3.1.1 iso.3.6.1.2.1.1.9.1.2.3 = OID: iso.3.6.1.6.3.11.3.1.1 iso.3.6.1.2.1.1.9.1.2.4 = OID: iso.3.6.1.6.3.15.2.1.1 iso.3.6.1.2.1.1.9.1.2.5 = OID: iso.3.6.1.6.3.16.2.1.1 iso.3.6.1.2.1.1.9.1.3.1 = STRING: "The MIB Module from SNMPv2 entities" iso.3.6.1.2.1.1.9.1.3.2 = STRING: "SNMP Management Architecture MIB" iso.3.6.1.2.1.1.9.1.3.3 = STRING: "Message Processing and Dispatching MIB" iso.3.6.1.2.1.1.9.1.3.4 = STRING: "USM User MIB" iso.3.6.1.2.1.1.9.1.3.5 = STRING: "VACM MIB" iso.3.6.1.2.1.1.9.1.4.1 = Timeticks: (0) 0:00:00.00 iso.3.6.1.2.1.1.9.1.4.2 = Timeticks: (0) 0:00:00.00 iso.3.6.1.2.1.1.9.1.4.3 = Timeticks: (0) 0:00:00.00 iso.3.6.1.2.1.1.9.1.4.4 = Timeticks: (0) 0:00:00.00 iso.3.6.1.2.1.1.9.1.4.5 = Timeticks: (0) 0:00:00.00 iso.3.6.1.2.1.2.1.0 = INTEGER: 2 iso.3.6.1.2.1.2.2.1.1.1 = INTEGER: 1 iso.3.6.1.2.1.2.2.1.1.2 = INTEGER: 2 iso.3.6.1.2.1.2.2.1.2.1 = STRING: "LOOPBACK" iso.3.6.1.2.1.2.2.1.2.2 = STRING: "eth0" iso.3.6.1.2.1.2.2.1.3.1 = INTEGER: 24 iso.3.6.1.2.1.2.2.1.3.2 = INTEGER: 6 iso.3.6.1.2.1.2.2.1.4.1 = INTEGER: 1500 iso.3.6.1.2.1.2.2.1.4.2 = INTEGER: 1500 etc....
-
Oh, and if I just want to pull one of the items I just specify the iso number with the snmpget command. E.g
local command = io.popen("ssh -i /etc/dropbear/dropbear_rsa_host_key pi@192.168.102.37 'snmpget -v1 -c public 10.10.10.103 iso.3.6.1.2.1.1.1.0' 2>&1") local response = command:read("*a") print(response)
which in this case will just return the first one.
iso.3.6.1.2.1.1.1.0 = STRING: "Eaton 5P 1150"
-
I use a lua scene to read snmp network usage from my switches. Working great for a couple of years now.
-
propheadreplied to parkerc on Jul 7, 2021, 10:22 PM last edited by prophead Jul 7, 2021, 6:28 PM
@parkerc Yes, I have 3 lua scenes, one for each switch for LAN monitoring and one for my Edgerouter for WAN monitoring. Each uses the same basic snmp framework with device specific tweaks and then saves results to an empty device and then I graph those device variables. I'm happy to share my code below:
-
@parkerc this is the Dlink 8 port SNMP switch lua:
-- SNMP 8 port BWmon -- read stored in/out values local lines = "" local Din = {} local Dout = {} local Oin = {} local Oout = {} local Nin = {} local Nout = {} local T = {} local i,j --check for switch local ping = os.execute("ping -c 1 192.168.1.11") if ping ~= 0 then luup.log("Dlink 8: Switch down. Aborted.") do return end end for i = 1,8 do -- read stored values local f = io.open("/tmp/8"..i.."I.txt") if f then for line in f:lines() do lines = line end -- for each line f:close() else os.execute("touch /tmp/8"..i.."I.txt") end if not lines then lines = "0" end Oin[i] = lines --print (Oin[i]) local f = io.open("/tmp/8"..i.."O.txt") if f then for line in f:lines() do lines = line end -- for each line f:close() else os.execute("touch /tmp/8"..i.."O.txt") end if not lines then lines = "0" end Oout[i] = lines --print (Oout[i]) end -- for each port read -- parse values for j = 1,8 do Oin[j] = string.match(Oin[j], ".*Counter32: (%d+)") if Oin[j] == "" or Oin[j] == nil then Oin[j] = 0 end Oout[j] = string.match(Oout[j], ".*Counter32: (%d+)") if Oout[j] == "" or Oout[j] == nil then Oout[j] = 0 end -- read snmp lines = "" os.execute("/usr/bin/snmpget -r 1 -v1 -c PASSWORD 192.168.1.11 iso.3.6.1.2.1.2.2.1.10."..j.." >/tmp/8"..j.."I.txt") local f = io.open("/tmp/8"..j.."I.txt") if not f then return end for line in f:lines() do lines = line end f:close() Nin[j] = lines --print (Nin[j]) lines = "" os.execute("/usr/bin/snmpget -r 1 -v1 -c PASSWORD 192.168.1.11 iso.3.6.1.2.1.2.2.1.16."..j.." >/tmp/8"..j.."O.txt") local f = io.open("/tmp/8"..j.."O.txt") if not f then return end for line in f:lines() do lines = line end f:close() Nout[j] = lines --print (Nout[j]) --parse Nin[j] = string.match(Nin[j], ".*Counter32: (%d+)") if Nin[j] == "" or Nin[j] == nil then Nin[j] = 0 end Nout[j] = string.match(Nout[j], ".*Counter32: (%d+)") if Nout[j] == "" or Nout[j] == nil then Nout[j] = 0 end --print (Nin[j]) --print (Nout[j]) --deltas Din[j] = Nin[j] - Oin[j] Dout[j] = Nout[j] - Oout[j] local max32 = 4294967295 --local max32 = 4294966864 -- handle rotation if Nin[j] < Oin[j] then Din[j] = max32 - Oin[j] + Nin[j] end if Nout[j] < Oout[j] then Dout[j] = max32 - Oout[j] + Nout[j] end if Din[j] > max32 or Din[j]<0 then Din[j] = 0 end --math.max(Oin[j],Nin[j]) end if Dout[j] > max32 or Dout[j]<0 then Dout[j] = 0 end --math.max(Oout[j],Nout[j]) end end -- end for each port write -- add real time interval tracking -- read old time lines = "" local ot = "" local f = io.open("/tmp/lastDlink8run.txt") if not f then os.execute("touch /tmp/lastDlink8run.txt") return end for line in f:lines() do ot = line end f:close() if not ot then ot = "300" end -- default to five minutes -- write new time local nt = tonumber(os.time()) local t = assert(io.open("/tmp/lastDlink8run.txt", "w"), "Failed to open lastDlink8run.txt") t:write(nt) io.close(t) -- delta seconds local nds = nt - ot -- bounds if nds < 24 then nds = 24 end if nds > 900 then nds = 900 end -- debugging local t = assert(io.open("/tmp/Dlink8nds.txt", "w"), "Failed to open Dlink8nds.txt") t:write(nds) io.close(t) -- maths for k = 1,8 do Din[k] = ((Din[k]/nds)/1024) if Din[k] > 1500000 then Din[k] = 0 end Dout[k] = ((Dout[k]/nds)/1024) if Dout[k] > 1500000 then Dout[k] = 0 end T[k] = Din[k]+Dout[k] end -- end for each K conversion -- set luup device variables for device 12, LAN luup.variable_set("urn:upnp-org:serviceId:altui1", "DoorBirdINKBps", Din[1] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "DoorBirdOUTKBps", Dout[1] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "DoorBirdKBps", T[1] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "RoomHubINKBps", Din[2] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "RoomHubOUTKBps", Dout[2] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "RoomHubKBps", T[2] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "BedroomINKBps", Din[3] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "BedroomOUTKBps", Dout[3] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "BedroomKBps", T[3] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "DownstairsINKBps", Din[4] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "DownstairsOUTKBps", Dout[4] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "DownstairsKBps", T[4] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "LivingRoomINKBps", Din[5] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "LivingRoomOUTKBps", Dout[5] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "LivingRoomKBps", T[5] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "KitchenINKBps", Din[6] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "KitchenOUTKBps", Dout[6] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "KitchenKBps", T[6] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "UpstairsINKBps", Din[7] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "UpstairsOUTKBps", Dout[7] , 12) luup.variable_set("urn:upnp-org:serviceId:altui1", "UpstairsKBps", T[7] , 12)
-
Altui on a pi
-
Impressive stuff, thanks for sharing @prophead ..
Earlier you mentioned ‘ Edgerouter’ , does that mean you have a Ubiquiti router ? If so would you be able to share the scene Lua for that, as I have a Unfi set up so would love to test that out..
-
-- SNMP BWmon -- read stored in/out values local files = "" local f = io.open("/tmp/INO.txt") if not f then os.execute("touch /tmp/INO.txt") end for line in f:lines() do files = line end f:close() local OINO = files local f = io.open("/tmp/OUTO.txt") if not f then os.execute("touch /tmp/OUTO.txt") end for line in f:lines() do files = line end f:close() if not files then files = "Counter32: (0)" end local OOUTO = files -- parse values local ROINO = string.match(OINO, ".*Counter32: (%d+)") local ROOUTO = string.match(OOUTO, ".*Counter32: (%d+)") -- read snmp os.execute("/usr/bin/snmpget -r 1 -v1 -c PASSWORD 172.16.0.1 iso.3.6.1.2.1.2.2.1.10.4 >/tmp/INO.txt") local f = io.open("/tmp/INO.txt") if not f then return end for line in f:lines() do files = line end f:close() local INO = files --print (INO) files = "" os.execute("/usr/bin/snmpget -r 1 -v1 -c PASSWORD 172.16.0.1 iso.3.6.1.2.1.2.2.1.16.4 >/tmp/OUTO.txt") local f = io.open("/tmp/OUTO.txt") if not f then return end for line in f:lines() do files = line end f:close() local OUTO = files --print (OUTO) --parse local RINO = 0 RINO = string.match(INO, ".*Counter32: (%d+)") local ROUTO = 0 ROUTO = string.match(OUTO, ".*Counter32: (%d+)") --print (RINO) --print (ROUTO) --maths local RINB = 0 RINB = RINO --* 8 local ROINB = 0 ROINB = ROINO --* 8 local ROUTB = 0 ROUTB = ROUTO --* 8 local ROOUTB = 0 ROOUTB = ROOUTO --* 8 --deltas local INt = 0 INt = RINB - ROINB local OUTt = 0 OUTt = ROUTB - ROOUTB local max32 = 4294966864 --debug --luup.log ('RINB ='..RINB..', ROINB ='..ROINB) --luup.log ('ROUTB ='..ROUTB..', ROOUTB ='..ROOUTB) -- handle rotation if RINB < ROINB then INt = max32 - ROINB + RINB end if ROUTB < ROOUTB then OUTt = max32 - ROOUTB + ROUTB end if INt > max32 or INt<0 then INt = max(RINB,ROINB) end if OUTt > max32 or OUTt<0 then OUTt = max(ROUTB,ROOUTB) end --luup.log ('INt ='..INt..', OUTt ='..OUTt) -- 60 is 1 min interval and 1024 makes kBps local kbpsINt = ((INt/60)/1024) local kbpsOUTt = ((OUTt/60)/1024) local total = kbpsINt + kbpsOUTt luup.variable_set("urn:upnp-org:serviceId:altui1", "ComcastKBps", total, 11) luup.variable_set("urn:upnp-org:serviceId:altui1", "ComcastInKBps", kbpsINt, 11) luup.variable_set("urn:upnp-org:serviceId:altui1", "ComcastOutKBps", kbpsOUTt, 11)
-
Quick observation, if I try the following against my UniFi (USG) Router
local command = io.popen("ssh -y -i /etc/dropbear/dropbear_rsa_host_key pi@192.168.102.144 'snmpget -r 1 -v1 -c public 192.168.102.1 iso.3.6.1.2.1.2.2.1.10.4' 2>&1") local response = command:read("*a") print(response)
it times out..
Timeout: No Response from 192.168.102.1.
Yet if I try this against a UniFi Switch,
local command = io.popen("ssh -y -i /etc/dropbear/dropbear_rsa_host_key pi@192.168.102.144 'snmpget -r 1 -v1 -c public 192.168.102.7 iso.3.6.1.2.1.2.2.1.10.4' 2>&1") local response = command:read("*a") print(response)
it works fine.
iso.3.6.1.2.1.2.2.1.10.4 = Counter32: 29157590
Hummm..
-
I tried an snmpwalk on the UniFi (USG) Router too,
'snmpwalk -Os -c public -v 1 192.168.102.1' 2>&1
and that timed out..
More digging is needed later, as all seem to have SNMP enabled..
-
@parkerc sounds like a permissions issue. Debug on command line before trying to script. I would also avoid use of the public access to snmp as it’s a potential security issue. I always setup private domain the proceedure differs by manufacturers. You can use snmpwalk for debugging then move to snmpget once you’re ready to drill down. Good luck.