SNMP v2c
Zeus.Protocols.Snmp 面向交换机、UPS、服务器、环境监控器和工业网关等带 SNMP Agent 的设备。当前支持 SNMP v2c 的单 OID GET/SET、常用变量类型、OID 点表采集、按点名写回、JSON 配置和虚拟 Agent 联调。
安装
dotnet add package Zeus.Communications
dotnet add package Zeus.Protocols.Snmp
SNMP 通常使用 UDP 161 端口。通道仍只负责收发字节,community、request-id 和 BER 编解码由 SnmpClient 处理。
无硬件联调
先用内存 Agent 验证点表和写回:
using Zeus;
var memory = new SnmpAgentMemory();
memory.SetGauge32("1.3.6.1.4.1.55555.1.1.0", 253, writable: true);
memory.SetText("1.3.6.1.4.1.55555.1.2.0", "rack-a", writable: true);
await using var app = ZeusHost.Create(builder =>
{
builder.AddAcquisition(TimeSpan.FromMilliseconds(500));
builder.AddVirtualChannel("snmp-link", new SnmpAgentResponder(memory));
builder.AddSnmp(
"agent",
"snmp-link",
points: map => map
.Gauge32("temperature", "1.3.6.1.4.1.55555.1.1.0", scale: 0.1)
.Writable("temperature")
.Text("location", "1.3.6.1.4.1.55555.1.2.0"));
});
await app.StartAsync();
Console.WriteLine(app.Points.Get<double>("temperature"));
await app.Points.WriteAsync("temperature", 18.6);
SnmpAgentMemory 预置了 sysDescr.0、sysUpTime.0 和可写的 sysName.0,也可以通过 Set、SetGauge32、SetText 等方法添加现场 MIB。
连接真实设备
把虚拟通道替换成 UDP 客户端:
await using var app = ZeusHost.Create(builder =>
{
builder.AddUdpClient("snmp-link", "192.168.1.20", 161);
builder.AddSnmp(
"switch",
"snmp-link",
new SnmpOptions
{
Community = "public",
WriteCommunity = "private"
},
points: map => map
.Integer("ifNumber", "1.3.6.1.2.1.2.1.0")
.Counter32("ifInOctets", "1.3.6.1.2.1.2.2.1.10.1"));
});
await app.StartAsync();
设备若只允许读取,可以省略 WriteCommunity,并且不要把点标为可写。
直接读写
var agent = app.Devices.Get<SnmpDevice>("switch");
var name = await agent.Client.GetTextAsync("1.3.6.1.2.1.1.5.0");
var uptime = await agent.Client.GetAsync("1.3.6.1.2.1.1.3.0");
await agent.Client.SetAsync("1.3.6.1.2.1.1.5.0", SnmpValue.Text("edge-01"));
SnmpClient 会串行化同一通道上的请求,并校验 response request-id、PDU 类型、OID 和错误状态。
点表类型
| API | SNMP 类型 | Zeus 值 |
|---|---|---|
Integer | INTEGER | long,可选 scale 后为 double |
Gauge32 | Gauge32 | uint,可选 scale 后为 double |
Counter32 | Counter32 | uint,可选 scale 后为 double |
TimeTicks | TimeTicks | uint,可选 scale 后为 double |
Text | OCTET STRING | UTF-8 string |
OctetString | OCTET STRING | byte[] |
ObjectIdentifier | OBJECT IDENTIFIER | OID string |
IpAddress | IpAddress | IPv4 string |
数值点支持报警限。写回时 scale 会反向换算,例如采集值 25.3、scale: 0.1 会向 Agent 写入原始值 253。
JSON 配置
{
"acquisition": { "intervalMilliseconds": 500, "pollImmediately": true },
"channels": [
{ "name": "snmp-link", "type": "virtual", "responder": "snmp" }
],
"devices": [
{
"name": "agent",
"channel": "snmp-link",
"type": "snmp",
"snmpCommunity": "public",
"snmpWriteCommunity": "private",
"points": [
{
"name": "sysName",
"oid": "1.3.6.1.2.1.1.5.0",
"dataType": "text",
"writable": true
},
{
"name": "temperature",
"oid": "1.3.6.1.4.1.55555.1.1.0",
"dataType": "gauge32",
"scale": 0.1,
"lowAlarmLimit": 0,
"highAlarmLimit": 80
}
]
}
]
}
设备类型支持 snmp、snmp-v2c 和 snmpv2c。虚拟通道的 responder 使用 snmp;真实设备则把通道改为 udp,填写设备 IP 和 161 端口。
排查
| 现象 | 首先检查 |
|---|---|
| 请求超时 | 设备 IP、UDP 161、防火墙、Agent 是否开启 |
| authorizationError | read/write community 或 ACL 不匹配 |
| noSuchName | OID 不存在、实例后缀缺少 .0,或设备 MIB 不同 |
| wrongType | dataType 与设备 MIB 的实际 ASN.1 类型不一致 |
| 点表没有值 | OID、数据类型、首次采集时间和点表错误快照 |
现场排查时打开通道报文追踪,确认请求和响应是否来自同一个设备,以及 response request-id 是否匹配。