Nodejs中使用net-snmp库读取智慧站房的温湿度、空调等实时数据

时间:2022-07-24
本文章向大家介绍Nodejs中使用net-snmp库读取智慧站房的温湿度、空调等实时数据,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

前言

最近有一个项目中需要使用SNMP协议的get命令读取远程智慧站房的站房温度、湿度等实时数据,并且可以通过set命令对空调进行的控制。

网络走的是V**,知道远程主机的IP地址和community口令,以及对应每个设备的OID,就比较容易获取对应设备的实时数据,以及对空调进行开关控制了。

SNMP协议

概述: SNMP 支持 V1 、V2、V3协议,get,getnext 和 set 三种操作,由于设备所接的监控设备 丌同,扩展的模块多少和类型丌同,对应的监测量丌是固定的,所以设备没有固定的 MIB 库,监测量不 OID 对应的原则如内容所示。可以采用 getnext 遍历整个设备 MIB。对于监 测量的描述信息,采用 OCTET STRING,编码方式为 gb2312,对于开关量(输入和输 出),采用 INTEGER 类型,只有 0 和 1 两个值,对于模拟量(输入和输出),采用 OCTET STRING 表示,默认保留小数点后 4 位小数,对于枚举量,采用 INTEGER 表示,门禁等 信息 OCTET STRING 表示,表示方式遵循设备相应协议。

实时数据和监测点描述信息对应的 OID 结构描述如下图:

监测类型对应关系如下图所示:

空调的相关控制命令:

首先可以使用net-snmp等工具获取相关的oid信息,我使用的是Snmputilg.exe这个工具获取对应的站房温度、站房湿度、空调红外传感器1、空调红外传感器2的描述oid以及对应的值。对于空调控制来说,需要现场运维人员进行相应的学习:比如说自动模式、关灯指令,具体描述见上面的SNMP文档协议。

nodejs使用net-snmp库实现远程读取温湿度等环境实时数据,控制空调

关于nodejs中snmp库的选择,目前https://www.npmjs.com/search?q=snmp中比较流行的有如下两个nodejs库:

  • net-snmp This module implements versions 1, 2c and 3 of the Simple Network Management Protocol (SNMP).
  • snmp-node This is a native SNMP library for Node.js. The purpose is to provide enough functionality to perform large scale monitoring of network equipment. Current features towards this end are:
  • Full implementation of SNMPv2c, including 64 bit data types.
  • Support for Get, GetNext and Set requests, with optimizations such as GetAll and GetSubtree.
  • No unusual external dependencies, no non-JavaScript code.
  • Very high performance, unlimited parallellism. (There are always limits. However, there are no arbitrary such imposed by this code and you at least won’t run out of file descriptors.)
  • De facto standards compliance. Generated packets are compared against Net-SNMP and should be identical in all relevant aspects.
  • Well tested. Test coverage should be at or close to 100% for all important code paths.

我使用的是net-snmp这个Nodejs库。

使用nodejs和net-snmp的js代码如下:

var snmp = require ("net-snmp");
var moment = require('moment');
const nodemon = require("nodemon");

var session = snmp.createSession ("15.129.13.267", "public");

// 15.129.13.267  靖屏大道站  学习了“开”和“关”两个指令

// 温湿度模块1 模拟量输入(AI1) 站房温度 27.40 无告警 连接正常

// 温湿度模块1 模拟量输入(AI2) 站房湿度 46.40 无告警 连接正常

// 站房温度
// 监测点配置(类型:模拟量输入AI,地址:1,索引:1)
// 1.3.6.1.4.1.50688.2.4.1.1.0

// 站房湿度
// 监测点配置(类型:模拟量输入AI,地址:1,索引:2)
// 1.3.6.1.4.1.50688.2.4.1.2.0
// 命令=GET: OID=1.3.6.1.4.1.50688.2.4.1.2.0; 值=5110

var items = [
	{name: '站房温度', oid: '1.3.6.1.4.1.50688.2.4.1.1.0'}, 
	{name: '站房湿度', oid: '1.3.6.1.4.1.50688.2.4.1.2.0'},
	{name: '空调控制指令1', oid: '1.3.6.1.4.1.50688.2.9.256.1.0'},
	{name: '空调控制指令2', oid: '1.3.6.1.4.1.50688.2.9.256.2.0'}
];

// snmpset 控制空调
// 控制空调之前,需要现场学习对应的指令,目前空调控制器有两个红外探头,有两个通道
// 开空调
// 自动模式 00 自动模式、风速-自动、上下扫风、左右扫风
function openAirCondition() {
this.set('1.3.6.1.4.1.50688.2.9.256.1.0', 0);
}

// 关空调
// 关机 63 可以再任何模式下学习
function closeAirCondition() {
this.set('1.3.6.1.4.1.50688.2.9.256.1.0', 63);
}

function set(strOid, iVal) {
var varbinds = [
	{
		oid: strOid,
		type: netsnmp.ObjectType.Integer,
		value: iVal
	}
];

this.sessionObj.set (varbinds, function (error, varbinds) {
	if (error) {
		console.error (error.toString ());
	} else {
			// for version 1 we can assume all OIDs were successful
			console.log (varbinds.oid + "|" + varbinds.value);
		
			// for version 2c we must check each OID for an error condition
			if (netsnmp.isVarbindError (varbinds))
				console.error (netsnmp.varbindError (varbinds));
			else
				console.log (varbinds.oid + "|" + varbinds.value);
	}
});
}


// 获取数据
function getData() {
	var oids = [];
	items.forEach((val, index) => {
		oids.push(val.oid);
	});
	session.get (oids, function (error, varbinds) {
		if (error) {
			console.error (error);
		} else {
			for (var i = 0; i < varbinds.length; i++)
				if (snmp.isVarbindError (varbinds[i]))
					console.error (snmp.varbindError (varbinds[i]))
				else
					console.log (varbinds[i].oid + " = " + varbinds[i].value);
		}
		//session.close ();
	});
}

session.trap (snmp.TrapType.LinkDown, function (error) {
    if (error)
        console.error (error);
});


// 每隔2秒钟获取一次当前站房的温湿度、空调红外传感器1和空调红外传感器2的值
setInterval(()=>{
	let nowTime = moment().format('YYYY-MM-DD HH:mm:ss');
	console.log('当前时间为:', nowTime);
	getData();
}, 2000);

运行结果如下图所示:

参考资料