请选择 进入手机版 | 继续访问电脑版

UBAINS

 找回密码
 立即注册
搜索
热搜: UBAINS
查看: 3849|回复: 0

[设备模板] ModbusTCP的简单实现读取和写寄存器值

[复制链接]

10

主题

11

帖子

449

积分

版主

Rank: 7Rank: 7Rank: 7

积分
449
QQ
发表于 2021-8-30 12:14:16 | 显示全部楼层 |阅读模式

  1. /**
  2. * @description ModbusTCP 的简单实现,读取和写寄存器值,并将寄存器状态值本地保存
  3. *              当某地址的寄存器值变化后触发 event 函数处理
  4. * @author pidtfork
  5. * @date 2021-08-30
  6. * @param {String} address  从机或网关的IP地址
  7. * @param {Number|String} port 从机或网关的端口 (协议默认为502)
  8. * @param {Number} slaveID  从机或网关的 ID
  9. */
  10. function ModbusTCP(address, port, slaveID) {
  11.     this.msgID = 0;
  12.     this.version = "\x00\x00";
  13.     this.slaveID = slaveID || 1;
  14.     this.statusList = {};
  15.     var self = this;
  16.     // 1 事务处理标识   两个字节高字节在前
  17.     // 2 协议标识       两个字节高字节在前
  18.     // 3 长度           两个字节高字节在前
  19.     // 4 单元标识       1个字节0x00 ¡ 0xff
  20.     // 6 功能码         1个字节0x03
  21.     // 7 起始寄存器地址 两个字节高字节在前
  22.     // 8 寄存器个数     两个字节高字节在前
  23.     this.read = function (addr) {
  24.         var len = arguments[1] || 1;
  25.         // 事务标识用用要读的寄存器起始地址为标识,方便响应数据处理
  26.         // 读寄存器 第一个长度固定为6
  27.         var code = this.doubleByte(addr) + this.version + this.doubleByte(6);
  28.         code = code + this.byte(this.slaveID) + "\x03";
  29.         code = code + this.doubleByte(addr) + this.doubleByte(len);
  30.         // 发送数据
  31.         dev.sendCodeString(code);
  32.     }
  33.     // 寄多个存器地址, 数组类型数值
  34.     // 1 事务处理标识两个字节高字节在前
  35.     // 2 协议标识两个字节高字节在前
  36.     // 3 长度两个字节高字节在前
  37.     // 4 单元标识1个字节0x00 ¡ 0xff
  38.     // 5 功能码1个字节0x10
  39.     // 6 起始寄存器地址两个字节高字节在前
  40.     // 7 寄存器个数两个字节 高字节在前
  41.     // 8 数据长度 1个字节 寄存器个数£2 
  42.     // 9 数据寄存器个数£2个字节每个寄存器高字节在前
  43.     this.write = function (addr, arrValue) {
  44.         var len = arrValue.length * 2;
  45.         var code = this.getMsgID() + this.version + this.doubleByte(len + 7);
  46.         code = code + this.byte(this.slaveID) + "\x10";
  47.         code = code + this.doubleByte(addr) + this.doubleByte(arrValue.length) + this.byte(len);
  48.         for (var i = 0; i < arrValue.length; i++) {
  49.             var element = arrValue[i];
  50.             code = code + this.doubleByte(element);
  51.         }
  52.         // 发送数据
  53.         dev.sendCodeString(code);
  54.     }
  55.     this.getMsgID = function () {
  56.         if (this.msgID > 0xFFFE) {
  57.             this.msgID = 0;
  58.         }
  59.         this.msgID++;
  60.         return this.doubleByte(this.msgID);
  61.     }
  62.     this.byte = function (value) {
  63.         return String.fromCharCode(value);
  64.     }
  65.     this.doubleByte = function (value) {
  66.         if (value > 255) {
  67.             return this.byte(value >> 8) + this.byte(value & 0xFF);
  68.         }
  69.         return "\x00" + this.byte(value);
  70.     }
  71.     this.emit = function (addr, value) {
  72.         if (self.statusList[addr] != value) {
  73.             self.event(addr, value, self.statusList[addr] || 0);
  74.             self.statusList[addr] = value;
  75.         }
  76.     }
  77.     this.event = function (addr, value, old) { }
  78.     var receiveData = function (data) {
  79.         //任何响应都应大于10个字节
  80.         if (data.length > 10) {
  81.             var id = data.charCodeAt(6);
  82.             var funCode = data.charCodeAt(7);
  83.             // id为当前设备ID,功能码为读取寄存器状态的响应时处理数据
  84.             if (id == self.slaveID && funCode == 3) {
  85.                 // 每个寄存器的数据长度为2个字节 number 为寄存器个数
  86.                 var number = data.charCodeAt(8) / 2;
  87.                 // 事务标识为读寄存器的起始地址
  88.                 var startAddr = data.charCodeAt(0) * 256 + data.charCodeAt(1);
  89.                 var index = 9, addr, value;
  90.                 for (var i = 0; i < number; i++) {
  91.                     value = data.charCodeAt(index) * 256 + data.charCodeAt(index + 1);
  92.                     addr = startAddr + i;
  93.                     index = index + 2;
  94.                     self.emit(addr, value)
  95.                 }
  96.             }
  97.         }
  98.     }
  99.     var dev = new _TCP(address + ":" + port, receiveData);
  100. }


  101. //开始使用

  102. // 实例化 ModbusTCP 传入 从机的IP地址和服务端口,从机的ID值
  103. var devMode = new ModbusTCP('192.168.25.1', 502, 1);


  104. // 定时 1S 查询某地址寄存器的值
  105. // 这里是现场有面板可以改变这个寄存器的值,所以这里做一下同步
  106. // 定时去读取寄存器地址的值
  107. setInterval(1, function () {
  108.     // 读取 从寄存器地址 10005 开始,读 3个 寄存器的值
  109.     // 即 读 10005 10006 10007 三个寄存器的值
  110.     // 地址值为10进制值,如果是16进制请先转换
  111.     devMode.read(10005, 3);
  112. })

  113. //写寄存器值时,第一个参数为寄存器地址 地址值为10进制值,如果是16进制请先转换
  114. // 参数2 必须为数组, 可以连续写多个寄存器,
  115. // 参数2 即使写一个值也必须为数组

  116. // devMode.write(10005,[1]); // 写寄存器值,将地址10005值设置为1
  117. // devMode.write(10006,[1]); // 写寄存器值,将地址10006值设置为1
  118. // devMode.write(10007,[1]); // 写寄存器值,将地址10007值设置为1
  119. // devMode.write(10005,[0]); // 写寄存器值,将地址10005值设置为0
  120. // devMode.write(10006,[0]); // 写寄存器值,将地址10006值设置为0
  121. // devMode.write(10007,[0]); // 写寄存器值,将地址10007值设置为0

  122. // devMode.write(10005,[1,1,1]); // 将地址10005 10006 10007值都设置为1
  123. // devMode.write(10005,[1,0,1]); // 将地址10005 10007值设置为1 10006 设置为0


  124. // 重写 event  方法, 此方法 读到 在寄存器地址的值变化后主动触发执行
  125. // event 方法可接收3 个参数
  126. // 参数1 addr 为 寄存器地址
  127. // 参数2 value 为 此寄存器的当前值
  128. // 参数3 old 为 此寄存器的上一次的值
  129. // 例如 devMode.read(10005, 3); 读取到 10005/10006/10007值都变化时 devMode.event 调用3次
  130. devMode.event = function (addr, value, old) {
  131.     switch (addr) {
  132.         case 10005:
  133.             if (value) {
  134.                 setButtonImage("AWM1", "ImageOnStates.png")
  135.             } else {
  136.                 setButtonImage("AWM1", "ImageOffStates.png")
  137.             }
  138.             break;
  139.         case 10006:
  140.             if (value) {
  141.                 setButtonImage("AWM2", "ImageOnStates.png")
  142.             } else {
  143.                 setButtonImage("AWM2", "ImageOffStates.png")
  144.             }
  145.             break;
  146.         case 10007:
  147.             if (value) {
  148.                 setButtonImage("AWM3", "ImageOnStates.png")
  149.             } else {
  150.                 setButtonImage("AWM3", "ImageOffStates.png")
  151.             }
  152.             break;
  153.         default:
  154.             break;
  155.     }
  156. }
复制代码


附件为此帖子的js文件和modbus tcp协议说明


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
高级模式
B Color Image Link Quote Code Smilies |上传

本版积分规则

Archiver|手机版|小黑屋|BBS.UBAINSYUN.COM

GMT+8, 2024-11-3 07:44 , Processed in 0.039859 second(s), 20 queries .

Powered by UBAINS! X3.4

© 2001-2017 UBAINS Inc.

快速回复 返回顶部 返回列表