|
- /**
- * @description ModbusTCP 的简单实现,读取和写寄存器值,并将寄存器状态值本地保存
- * 当某地址的寄存器值变化后触发 event 函数处理
- * @author pidtfork
- * @date 2021-08-30
- * @param {String} address 从机或网关的IP地址
- * @param {Number|String} port 从机或网关的端口 (协议默认为502)
- * @param {Number} slaveID 从机或网关的 ID
- */
- function ModbusTCP(address, port, slaveID) {
- this.msgID = 0;
- this.version = "\x00\x00";
- this.slaveID = slaveID || 1;
- this.statusList = {};
- var self = this;
- // 1 事务处理标识 两个字节高字节在前
- // 2 协议标识 两个字节高字节在前
- // 3 长度 两个字节高字节在前
- // 4 单元标识 1个字节0x00 ¡ 0xff
- // 6 功能码 1个字节0x03
- // 7 起始寄存器地址 两个字节高字节在前
- // 8 寄存器个数 两个字节高字节在前
- this.read = function (addr) {
- var len = arguments[1] || 1;
- // 事务标识用用要读的寄存器起始地址为标识,方便响应数据处理
- // 读寄存器 第一个长度固定为6
- var code = this.doubleByte(addr) + this.version + this.doubleByte(6);
- code = code + this.byte(this.slaveID) + "\x03";
- code = code + this.doubleByte(addr) + this.doubleByte(len);
- // 发送数据
- dev.sendCodeString(code);
- }
- // 寄多个存器地址, 数组类型数值
- // 1 事务处理标识两个字节高字节在前
- // 2 协议标识两个字节高字节在前
- // 3 长度两个字节高字节在前
- // 4 单元标识1个字节0x00 ¡ 0xff
- // 5 功能码1个字节0x10
- // 6 起始寄存器地址两个字节高字节在前
- // 7 寄存器个数两个字节 高字节在前
- // 8 数据长度 1个字节 寄存器个数£2
- // 9 数据寄存器个数£2个字节每个寄存器高字节在前
- this.write = function (addr, arrValue) {
- var len = arrValue.length * 2;
- var code = this.getMsgID() + this.version + this.doubleByte(len + 7);
- code = code + this.byte(this.slaveID) + "\x10";
- code = code + this.doubleByte(addr) + this.doubleByte(arrValue.length) + this.byte(len);
- for (var i = 0; i < arrValue.length; i++) {
- var element = arrValue[i];
- code = code + this.doubleByte(element);
- }
- // 发送数据
- dev.sendCodeString(code);
- }
- this.getMsgID = function () {
- if (this.msgID > 0xFFFE) {
- this.msgID = 0;
- }
- this.msgID++;
- return this.doubleByte(this.msgID);
- }
- this.byte = function (value) {
- return String.fromCharCode(value);
- }
- this.doubleByte = function (value) {
- if (value > 255) {
- return this.byte(value >> 8) + this.byte(value & 0xFF);
- }
- return "\x00" + this.byte(value);
- }
- this.emit = function (addr, value) {
- if (self.statusList[addr] != value) {
- self.event(addr, value, self.statusList[addr] || 0);
- self.statusList[addr] = value;
- }
- }
- this.event = function (addr, value, old) { }
- var receiveData = function (data) {
- //任何响应都应大于10个字节
- if (data.length > 10) {
- var id = data.charCodeAt(6);
- var funCode = data.charCodeAt(7);
- // id为当前设备ID,功能码为读取寄存器状态的响应时处理数据
- if (id == self.slaveID && funCode == 3) {
- // 每个寄存器的数据长度为2个字节 number 为寄存器个数
- var number = data.charCodeAt(8) / 2;
- // 事务标识为读寄存器的起始地址
- var startAddr = data.charCodeAt(0) * 256 + data.charCodeAt(1);
- var index = 9, addr, value;
- for (var i = 0; i < number; i++) {
- value = data.charCodeAt(index) * 256 + data.charCodeAt(index + 1);
- addr = startAddr + i;
- index = index + 2;
- self.emit(addr, value)
- }
- }
- }
- }
- var dev = new _TCP(address + ":" + port, receiveData);
- }
- //开始使用
- // 实例化 ModbusTCP 传入 从机的IP地址和服务端口,从机的ID值
- var devMode = new ModbusTCP('192.168.25.1', 502, 1);
- // 定时 1S 查询某地址寄存器的值
- // 这里是现场有面板可以改变这个寄存器的值,所以这里做一下同步
- // 定时去读取寄存器地址的值
- setInterval(1, function () {
- // 读取 从寄存器地址 10005 开始,读 3个 寄存器的值
- // 即 读 10005 10006 10007 三个寄存器的值
- // 地址值为10进制值,如果是16进制请先转换
- devMode.read(10005, 3);
- })
- //写寄存器值时,第一个参数为寄存器地址 地址值为10进制值,如果是16进制请先转换
- // 参数2 必须为数组, 可以连续写多个寄存器,
- // 参数2 即使写一个值也必须为数组
- // devMode.write(10005,[1]); // 写寄存器值,将地址10005值设置为1
- // devMode.write(10006,[1]); // 写寄存器值,将地址10006值设置为1
- // devMode.write(10007,[1]); // 写寄存器值,将地址10007值设置为1
- // devMode.write(10005,[0]); // 写寄存器值,将地址10005值设置为0
- // devMode.write(10006,[0]); // 写寄存器值,将地址10006值设置为0
- // devMode.write(10007,[0]); // 写寄存器值,将地址10007值设置为0
- // devMode.write(10005,[1,1,1]); // 将地址10005 10006 10007值都设置为1
- // devMode.write(10005,[1,0,1]); // 将地址10005 10007值设置为1 10006 设置为0
- // 重写 event 方法, 此方法 读到 在寄存器地址的值变化后主动触发执行
- // event 方法可接收3 个参数
- // 参数1 addr 为 寄存器地址
- // 参数2 value 为 此寄存器的当前值
- // 参数3 old 为 此寄存器的上一次的值
- // 例如 devMode.read(10005, 3); 读取到 10005/10006/10007值都变化时 devMode.event 调用3次
- devMode.event = function (addr, value, old) {
- switch (addr) {
- case 10005:
- if (value) {
- setButtonImage("AWM1", "ImageOnStates.png")
- } else {
- setButtonImage("AWM1", "ImageOffStates.png")
- }
- break;
- case 10006:
- if (value) {
- setButtonImage("AWM2", "ImageOnStates.png")
- } else {
- setButtonImage("AWM2", "ImageOffStates.png")
- }
- break;
- case 10007:
- if (value) {
- setButtonImage("AWM3", "ImageOnStates.png")
- } else {
- setButtonImage("AWM3", "ImageOffStates.png")
- }
- break;
- default:
- break;
- }
- }
复制代码
附件为此帖子的js文件和modbus tcp协议说明
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|