首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >多协议传感设备调试:以太网温湿度变送器 SNMP、TCP 通讯实战

多协议传感设备调试:以太网温湿度变送器 SNMP、TCP 通讯实战

原创
作者头像
盛世宏博小可
发布于 2026-09-23 13:11:12
发布于 2026-09-23 13:11:12
1840
举报

多协议传感设备调试:以太网温湿度变送器 SNMP、TCP 通讯实战

物联网 #Modbus #TCP/IP #UDP #SNMP #POE供电 #以太网温湿度传感器 #网口温湿度变送器 #工业现场 #环境监测 #Wireshark #Python

前面把 asyncio 高并发采集、多协议固件开发、EMC 电磁兼容、PoE 功率分配、双供电切换、Wireshark 排障、车间落地、现场测试全流程全部讲透了。这一篇聚焦一个非常实际的问题——当你拿到一台多协议以太网温湿度变送器,SNMP 和 TCP(Modbus TCP)两种协议都要用,调试时该怎么下手。

先说一个现场真实场景:

甲方要求:温湿度数据走 Modbus TCP 进动环平台做实时采集和联动,同时要求 SNMP 接入 IT 运维的 Zabbix 做设备存活监控和端口状态查看。 设备到了,你配好 IP,Modbus Poll 一跑,数据正常。然后打开 Zabbix,SNMP 模板挂上去,发现——读不到温度。 你以为是 SNMP 社区名不对,改了 public、private、自定义,都不行。 你以为是 OID 不对,用 snmpwalk 手动跑,发现设备返回 Timeout: No Response from 192.168.100.50。 你以为是防火墙拦了 UDP 161,关了防火墙还是不行。 最后发现:这台设备的 SNMP Agent 默认关闭,需要在 Web 管理界面手动启用。而你之前根本不知道这台设备有 Web 管理界面——说明书 200 页,这一行藏在第 147 页的"高级功能"里。


一、先搞清楚:你的设备到底支持什么

1. 三种常见多协议模式

模式

说明

典型设备

双栈并行​

SNMP Agent + Modbus TCP Server 同时运行,互不干扰

大多数中高端工业传感器

协议切换​

同一端口号可通过配置切换为 SNMP 或 Modbus TCP(不同时运行)

部分低端设备

网关模式​

设备本身是一个 SNMP Agent,但温湿度数据通过内部轮询 Modbus 从站获取

带多协议转换的工业网关

调试前必做:登录设备 Web 界面(或串口配置工具),确认 SNMP 和 Modbus TCP 是否同时启用。很多设备默认只开 Modbus TCP,SNMP 需要手动开启。

2. 快速确认清单

代码语言:javascript
复制
□ 设备是否有 Web 管理界面?(浏览器访问 IP)
□ SNMP 功能是否默认开启?(查看 Web 界面或说明书)
□ SNMP 版本支持:v1 / v2c / v3?(多数设备只支持 v2c)
□ 社区名(Community):默认 public?还是自定义?
□ SNMP 端口:默认 161?是否可修改?
□ Modbus TCP 端口:默认 502?是否可修改?
□ 两种协议是否共享同一 IP 和端口?还是独立端口?
□ 设备是否有 MIB 文件?(.mib 或 .txt 格式)

二、SNMP 调试实战

1. 从零开始的 SNMP 调试流程

代码语言:javascript
复制
第 1 步:确认 SNMP Agent 已启用
  → 浏览器登录设备 Web 界面
  → 找到 SNMP 配置页面
  → 确认 "Enable SNMP" 已勾选
  → 记录社区名、SNMP 版本、端口号

第 2 步:从命令行测试基础连通性
  → snmpwalk -v 2c -c public IP 1.3.6.1.2.1.1.1
  → 如果返回系统描述信息,说明 SNMP 基本正常

第 3 步:找到温湿度 OID
  → 用 snmpwalk 遍历整个 MIB 树
  → 或查阅设备 MIB 文件,找到温度/湿度对应的 OID

第 4 步:验证数据正确性
  → 对比 SNMP 读取值与 Modbus TCP 读取值
  → 确认缩放因子、数据类型一致

2. 常用 SNMP 命令行工具

代码语言:javascript
复制
# 安装(Ubuntu/Debian)
apt install snmp snmp-mibs-downloader

# 基础查询
snmpget -v 2c -c public 192.168.100.50 1.3.6.1.2.1.1.1.0
# 返回:系统描述(设备型号、固件版本等)

# 遍历子树
snmpwalk -v 2c -c public 192.168.100.50 1.3.6.1.4.1

# 指定 MIB 文件
snmptranslate -Td -m ./device.mib TEMP-SENSOR-MIB::temperature

# 批量查询
for oid in 1.3.6.1.4.1.50001.1.1.1 1.3.6.1.4.1.50001.1.1.2; do
    snmpget -v 2c -c public 192.168.100.50 $oid
done

# 持续监控(每 5 秒查询一次)
while true; do
    snmpget -v 2c -c public 192.168.100.50 1.3.6.1.4.1.50001.1.1.1.0
    sleep 5
done

3. Python SNMP 读取

代码语言:javascript
复制
from pysnmp.hlapi import *

def snmp_get(ip, community, oid):
    """SNMP GET 单个 OID"""
    iterator = getCmd(
        SnmpEngine(),
        CommunityData(community),
        UdpTransportTarget((ip, 161), timeout=2.0, retries=2),
        ContextData(),
        ObjectType(ObjectIdentity(oid))
    )
    
    errorIndication, errorStatus, errorIndex, varBinds = next(iterator)
    
    if errorIndication:
        print(f"SNMP 错误: {errorIndication}")
        return None
    elif errorStatus:
        print(f"SNMP 状态错误: {errorStatus.prettyPrint()}")
        return None
    else:
        for varBind in varBinds:
            return varBind[1].prettyPrint()

# 示例:读取温度和湿度
ip = "192.168.100.50"
community = "public"

# 假设 OID(需根据实际 MIB 替换)
temp_oid = "1.3.6.1.4.1.50001.1.1.1.0"
humid_oid = "1.3.6.1.4.1.50001.1.1.2.0"

temp = snmp_get(ip, community, temp_oid)
humid = snmp_get(ip, community, humid_oid)

print(f"温度: {temp} ℃")
print(f"湿度: {humid} %RH")

4. SNMP 常见问题排查

问题

现象

排查方法

解决

SNMP 未启用

snmpwalk 超时

登录 Web 界面检查

启用 SNMP Agent

社区名错误

No Such Name 或超时

尝试 public、private

确认设备配置的社区名

OID 不存在

No Such Instance

snmpwalk 遍历整棵树

查阅 MIB 文件确认正确 OID

数据类型不匹配

读到的数值异常大

检查数据类型(INTEGER/Float)

按 MIB 定义解析

缩放因子不对

温度显示 224 而不是 22.4

检查 MIB 中的 DISPLAY-HINT

应用缩放因子 ×0.1

UDP 被防火墙拦截

超时

检查 iptables / 交换机 ACL

放行 UDP 161

设备 SNMP 栈崩溃

偶尔响应,偶尔超时

重启设备后恢复

升级固件或限制查询频率


三、TCP(Modbus TCP)调试实战

1. Modbus TCP 调试流程

代码语言:javascript
复制
第 1 步:确认 TCP 502 端口可达
  → nc -zv IP 502
  → 或 telnet IP 502

第 2 步:用 Modbus Poll 读取寄存器
  → 连接 → TCP/IP → 输入 IP、端口 502
  → 设置从站 ID、功能码 03、起始地址、数量
  → 观察数据

第 3 步:验证数据格式
  → 确认寄存器类型(INT16/UINT16/INT32/Float)
  → 确认字节序(ABCD/CDAB/BADC/DCBA)
  → 确认缩放因子(×0.1 / ×0.01 / 无)

第 4 步:Python 脚本批量验证
  → 用 pymodbus 读取,自动对比预期值

2. Python Modbus TCP 读取

代码语言:javascript
复制
import asyncio
from pymodbus.client import AsyncModbusTcpClient

async def read_sensor(ip, port=502, slave_id=1):
    client = AsyncModbusTcpClient(ip, port=port, timeout=2.0)
    await client.connect()
    
    if not client.connected:
        print(f"❌ {ip} 连接失败")
        return
    
    # 读取保持寄存器 0-3(温度、湿度、PM2.5、压差)
    resp = await client.read_holding_registers(0, count=4, slave=slave_id)
    
    if resp.isError():
        print(f"❌ {ip} 读取失败: {resp}")
    else:
        temp = resp.registers[0] * 0.1
        humid = resp.registers[1] * 0.1
        pm25 = resp.registers[2]
        pressure = resp.registers[3]
        print(f"✅ {ip}:")
        print(f"   温度: {temp} ℃")
        print(f"   湿度: {humid} %RH")
        print(f"   PM2.5: {pm25} μg/m³")
        print(f"   压差: {pressure} Pa")
    
    await client.close()

# 批量读取
async def batch_read(ips):
    for ip in ips:
        await read_sensor(ip)

ips = ["192.168.100.50", "192.168.100.51", "192.168.100.52"]
asyncio.run(batch_read(ips))

3. Modbus TCP 常见问题排查

问题

现象

排查方法

解决

端口不可达

连接超时

nc -zv IP 502

检查设备是否启用 Modbus TCP

从站 ID 错误

返回非法功能码

尝试 ID 1、255、设备标签值

确认设备从站地址

地址偏移不对

读到 0 或乱码

尝试 0-based 和 1-based

确认组态软件地址模式

字节序不对

数值异常

读 UINT16 和 INT16 对比

调整字节顺序

缩放因子不对

数值偏大 10 倍

对比标准温湿度计

设置 ÷10 或 ×0.1

连接数满

偶尔连不上

检查已建立连接数

限制并发或重启设备

TCP Keepalive 未开

半开连接

Wireshark 抓包

开启 Keepalive


四、SNMP 与 Modbus TCP 数据对比验证

1. 为什么需要对比

场景

原因

甲方同时要求两种协议

动环用 Modbus,IT 运维用 SNMP

数据一致性验证

确认两种协议读到的数据一致

故障定位

如果 Modbus 读不到但 SNMP 能读到,说明 Modbus 配置有问题

验收测试

两种协议都要验证,确保功能完整

2. 对比脚本

代码语言:javascript
复制
import asyncio
from pymodbus.client import AsyncModbusTcpClient
from pysnmp.hlapi import *

async def compare_protocols(ip, snmp_community, modbus_port=502, slave_id=1):
    """对比 SNMP 和 Modbus TCP 读到的数据"""
    print(f"\n{'='*50}")
    print(f"设备: {ip}")
    print(f"{'='*50}")
    
    # Modbus TCP 读取
    mb_client = AsyncModbusTcpClient(ip, port=modbus_port, timeout=2.0)
    await mb_client.connect()
    
    if mb_client.connected:
        mb_resp = await mb_client.read_holding_registers(0, count=2, slave=slave_id)
        if not mb_resp.isError():
            mb_temp = mb_resp.registers[0] * 0.1
            mb_humid = mb_resp.registers[1] * 0.1
            print(f"Modbus TCP: 温度={mb_temp}℃, 湿度={mb_humid}%RH")
        else:
            print("Modbus TCP: 读取失败")
            mb_temp, mb_humid = None, None
    else:
        print("Modbus TCP: 连接失败")
        mb_temp, mb_humid = None, None
    
    await mb_client.close()
    
    # SNMP 读取(同步方式,简化示例)
    # 实际使用时需要安装 pysnmp 并配置正确的 OID
    print("SNMP: 需要配置正确的 OID(参考设备 MIB 文件)")
    print("  请手动执行: snmpwalk -v 2c -c public IP 1.3.6.1.4.1")
    
    # 如果两种协议都成功,对比数据
    if mb_temp is not None:
        print(f"\n数据对比提示:")
        print(f"  Modbus 温度: {mb_temp}℃")
        print(f"  SNMP 温度: 请手动对比")
        print(f"  偏差应 < 0.5℃(传感器自身精度)")

# 运行对比
ips = ["192.168.100.50"]
for ip in ips:
    asyncio.run(compare_protocols(ip, "public"))

五、Zabbix 集成实战

1. Zabbix SNMP 模板配置

代码语言:javascript
复制
步骤 1:创建主机
  → 配置 → 主机 → 创建主机
  → 主机名称: Sensor-A01
  → 群组: Temperature Sensors
  → 接口: SNMP, IP 地址, 端口 161

步骤 2:配置 SNMP 社区
  → 宏 → 创建宏
  → 宏: {$SNMP_COMMUNITY}
  → 值: public

步骤 3:创建监控项
  → 监控项 → 创建监控项
  → 名称: 温度
  → 类型: SNMPv2 代理
  → 键值: sensor.temp
  → SNMP OID: 1.3.6.1.4.1.50001.1.1.1.0
  → 信息类型: 数字(浮点数)
  → 单位: ℃
  → 更新间隔: 30s

步骤 4:创建触发器
  → 触发器 → 创建触发器
  → 名称: 温度过高
  → 表达式: last(/Sensor-A01/sensor.temp) > 30
  → 严重性: 警告

步骤 5:创建图形
  → 图形 → 创建图形
  → 名称: 温湿度趋势
  → 添加监控项: 温度、湿度

2. Zabbix Modbus TCP 配置

代码语言:javascript
复制
方法 1:使用 Zabbix 内置的 Modbus 监控项(Zabbix 5.0+)
  → 监控项类型: Modbus
  → 端点: tcp://192.168.100.50:502
  → 从站 ID: 1
  → 寄存器类型: Holding register
  → 寄存器地址: 0
  → 数据类型: INT16
  → 转换: ×0.1

方法 2:使用外部脚本(Zabbix agent + Python)
  → 编写 Python 脚本读取 Modbus TCP
  → Zabbix agent 调用脚本
  → 返回 JSON 格式数据

六、Wireshark 同时抓 SNMP 和 Modbus TCP

1. 抓包过滤器

代码语言:javascript
复制
# 同时抓 SNMP(UDP 161)和 Modbus TCP(TCP 502)
tcp port 502 or udp port 161

2. 显示过滤器

代码语言:javascript
复制
# SNMP 请求和响应
snmp

# Modbus TCP 请求和响应
modbus

# 同时看两种协议
tcp.port == 502 || udp.port == 161

# 按设备 IP 过滤
ip.addr == 192.168.100.50 && (tcp.port == 502 || udp.port == 161)

3. 分析要点

协议

关注点

SNMP

GET/GETNEXT 请求是否完整、响应是否超时、是否有 SNMPv3 认证失败

Modbus TCP

MBAP 头 Transaction ID 是否递增、功能码是否正确、寄存器数据是否合理

时间线

两种协议的请求是否互相影响(TCP 重传是否阻塞 UDP)


七、常见返工点

问题

后果

正确做法

不确认 SNMP 是否启用

调试半天发现功能没开

先登录 Web 界面确认

不查 MIB 文件

用错 OID

向厂家索要 MIB 文件

社区名用默认 public

安全审计不通过

改为自定义社区名

SNMP 和 Modbus 数据不一致

验收时被质疑

对比验证,确认缩放因子一致

Zabbix 模板用错数据类型

图形显示异常

确认 SNMP 返回的数据类型

不测试并发

现场同时跑两种协议出问题

同时发起 SNMP GET 和 Modbus 读取

不保存 MIB 文件

后期维护找不到 OID

归档 MIB 文件到项目文档


八、一句话总结

SNMP 和 Modbus TCP 在同一台设备上并存,调试的核心不是"会不会用工具",而是先搞清楚设备到底支持什么、默认开了什么、MIB 里定义了什么。 SNMP 调试记住四步:确认启用 → 命令行测试 → 找对 OID → 验证数据。 Modbus TCP 调试记住四步:端口可达 → 寄存器能读 → 字节序正确 → 缩放因子匹配。 两种协议都调通之后,一定要做数据对比——同一个物理量,两种协议读出来应该一致。不一致就说明哪里配错了,别等到验收时再发现。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 多协议传感设备调试:以太网温湿度变送器 SNMP、TCP 通讯实战
    • 物联网 #Modbus #TCP/IP #UDP #SNMP #POE供电 #以太网温湿度传感器 #网口温湿度变送器 #工业现场 #环境监测 #Wireshark #Python
    • 一、先搞清楚:你的设备到底支持什么
      • 1. 三种常见多协议模式
      • 2. 快速确认清单
    • 二、SNMP 调试实战
      • 1. 从零开始的 SNMP 调试流程
      • 2. 常用 SNMP 命令行工具
      • 3. Python SNMP 读取
      • 4. SNMP 常见问题排查
    • 三、TCP(Modbus TCP)调试实战
      • 1. Modbus TCP 调试流程
      • 2. Python Modbus TCP 读取
      • 3. Modbus TCP 常见问题排查
    • 四、SNMP 与 Modbus TCP 数据对比验证
      • 1. 为什么需要对比
      • 2. 对比脚本
    • 五、Zabbix 集成实战
      • 1. Zabbix SNMP 模板配置
      • 2. Zabbix Modbus TCP 配置
    • 六、Wireshark 同时抓 SNMP 和 Modbus TCP
      • 1. 抓包过滤器
      • 2. 显示过滤器
      • 3. 分析要点
    • 七、常见返工点
    • 八、一句话总结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档