1、功能简介

在阿里云物联网平台下发物模型属性设置数据,HaaS600Kit 接收并解析云端数据后控制 Modbus 继电器设备进行开关动作。

2、硬件连接

硬件平台:HaaS600开发板(EC600S-CN)、TTL转485串口板、Modbus继电器设备。

注意本示例中 HaaS600开发板需要5V DC接口供电,否则串口转接板工作时有可能因为供电不足导致系统重启。

2.1、HaaS600串口使用介绍

HaaS600 用户串口只有一个UART2,为了方便开发,板子上提供了USB2、J5和 J6 三处UART2 接口,其中 J5 和 J6 接口电压是 3.3V。注意使用 J5 和 J6 接口要把开关 K1 拨到丝印 JP 侧,开关 K3 用于调整串口TX RX顺序。本示例使用的TTL转485接口板使用J5接口,K3 拨到丝印 MASTER 侧。

3、云端控制

参考阿里云物联网平台帮助文档登陆阿里云官网,依次创建产品、创建设备后,添加物模型属性 PowerSwitch。

自定义的 PowerSwitch 属性和应用代码直接关联,下面介绍如何单个添加自定义物模型属性。

单个添加物模型属性

功能定义

编辑草稿

添加自定义功能

发布上线

在线调试

设置开启、关闭

4、串口日志

cloud onProps, msg_id is 1399004153
cloud onProps, params_len is 17
cloud onProps, params is {"PowerSwitch":1}
turn on relay
write send 1,5,0,0,255,0,140,58
rtn onData
onData: 1,5,0,0,255,0,140,58cloud onProps, msg_id is 1435839973
cloud onProps, params_len is 17
cloud onProps, params is {"PowerSwitch":0}
turn off relay
write send 1,5,0,0,0,0,205,202
rtn onData
onData: 1,5,0,0,0,0,205,202

参考代码

agriculture_demo.zip

app.js

把已创建设备的 ProductKey、ProductKey 和 DeviceSecret 填入到 app.js 代码中。

var iot = require('iot');
var network = require('network');var net = network.openNetWorkClient();var productKey = 'xxxx';      /* your productKey */
var deviceName = 'xxxx';      /* your deviceName */
var deviceSecret = 'xxxx';  /* your deviceSecret */var device;var modbus = require('./modbus.js');var deviceAddr = 1;
var timeout = 300;
var modbus_device = modbus({ id: 'UART2' },{ id: 'D13', polarity: 1 },deviceAddr
);function createDevice() {device = iot.device({productKey: productKey,deviceName: deviceName,deviceSecret: deviceSecret});var powerSwitch = 0;modbus_device.write(deviceAddr, 'c1', powerSwitch, timeout).then(function (data) {console.log('write c1 data ' + data);});device.on('connect', function () {console.log('(re)connected');/* post props */device.postProps(JSON.stringify({PowerSwitch: powerSwitch}));/* 云端下发服务事件 */device.onService(function (res) {console.log('cloud onService, msg_id is ' + res.msg_id);console.log('cloud onService, service_id is ' + res.service_id);console.log('cloud onService, params_len is ' + res.params_len);console.log('cloud onService, params is ' + res.params);});/* 云端设置属性事件 */device.onProps(function (res) {console.log('cloud onProps, msg_id is ' + res.msg_id);console.log('cloud onProps, params_len is ' + res.params_len);console.log('cloud onProps, params is ' + res.params);var payload = JSON.parse(res.params);powerSwitch = parseInt(payload.PowerSwitch);if(powerSwitch == 1) {console.log('turn on relay');} else {console.log('turn off relay');}modbus_device.write(deviceAddr, 'c1', powerSwitch, timeout).then(function (data) {console.log('write c1 data ' + data);});device.postProps(JSON.stringify({PowerSwitch: powerSwitch}));});});/* 网络断开事件 */device.on('disconnect', function () {console.log('disconnect ');});/* 关闭连接事件 */device.on('end', function () {console.log('iot client just closed');});/* 发生错误事件 */device.on('error', function (err) {console.log('error ' + err);});
}var status = net.getStatus();
console.log('net status is: ' + status);if (status == 'connect') {createDevice();
} else {net.on('connect', function () {console.log('net is connected success!');createDevice();});
}

modbus.js

function Modbus(uartPort, dirPort) {var rtn = {}var lastTid = 1rtn.readTimeout = 500;rtn.readTimeouthandler;rtn.packetBufferLength = 100rtn.packets = []rtn.stream = Serial(uartPort, dirPort)rtn.protocal = 'rtu'rtn.read = function (unitId, address, timeout, callback) {var parsedAddress = parseAddress(address)var funcCode = parsedAddress.fcReadvar length = parsedAddress.lengthaddress = parsedAddress.addressrtn.readTimeout = timeoutrtn.readTimeouthandler = setTimeout(function() {rtn.packets[tid].promiseReject('timeout')}, rtn.readTimeout)var tid = getTid()var buff = makeDataPacket(tid, 0, unitId, funcCode, address, null, length)if (rtn.protocal == 'rtu') { buff = buff.rtu }var packet = {onResponce: callback,tx: {funcCode: funcCode,tid: tid,address: address,hex: buff.toString('hex')},promiseResolve: null,promiseReject: null,rx: null}rtn.packets[tid] = packetrtn.stream.send(buff)console.log('read send ' + buff.toString('hex'))return new Promise(function (resolve, reject) {rtn.packets[tid].promiseResolve = resolvertn.packets[tid].promiseReject = reject})}rtn.write = function (unitId, address, value, timeout, callback) {var parsedAddress = parseAddress(address)var funcCode = parsedAddress.fcWritevar length = parsedAddress.lengthaddress = parsedAddress.addressvar tid = getTid()rtn.readTimeout = timeoutrtn.readTimeouthandler = setTimeout(function() {rtn.packets[tid].promiseReject('timeout')}, rtn.readTimeout)if (funcCode == 5 && value == true) { value = 65280 } // To force a coil on you send FF00 not 0001var buff = makeDataPacket(tid, 0, unitId, funcCode, address, value, length)if (rtn.protocal == 'rtu') { buff = buff.rtu }// console.log('buff ' + buff)var packet = {onResponce: callback,tx: {funcCode: funcCode,tid: tid,address: address,hex: buff.toString('hex')},rx: null}rtn.packets[tid] = packetrtn.stream.send(buff)console.log('write send ' + buff.toString('hex'))return new Promise(function (resolve, reject) {rtn.packets[tid].promiseResolve = resolvertn.packets[tid].promiseReject = reject})}var getTid = function () {if (lastTid > rtn.packetBufferLength) { lastTid = 0 }lastTid++if (rtn.protocal == 'rtu') { lastTid = 0 }return lastTid}rtn.stream.onData = function (buf) {console.log('onData: ' + buf.toString('hex'))var modbusResif (rtn.protocal == "rtu") { modbusRes = parseResponseRtu(buf) }var value = modbusRes.valuevar tid = modbusRes.tidif (rtn.protocal == "rtu") { tid = 0 }var err = nullif (modbusRes.exceptionCode) { err = 'Exception Code: 02 - Illegal Data Address' }rtn.packets[tid].rx = modbusResrtn.packets[tid].rx.hex = buf.toString('hex')if (typeof (rtn.packets[tid].onResponce) == "function") {rtn.packets[tid].onResponce(err, value)}if (err) {rtn.packets[tid].promiseReject(err)}else {// console.log('raw data:', value)rtn.packets[tid].promiseResolve(value)clearTimeout(rtn.readTimeouthandler)}}return rtn
}function parseResponseRtu(buffer) {var res = {}res.tid = 1var buf = new Buffer(buffer)res.unitId = buf.readInt8(0)                     //Unit Id        - Byte 6res.funcCode = buf.readInt8(1)                     //Function Code  - Byte 7res.byteCount = Math.abs(buf.readInt8(2))           //Byte Count     - Byte 8if (buf.length > 3) {// res.value = buf.readIntBE(3, buf.length - 5)       //Data           - Bytes 9+// var arr = Array.prototype.slice.call(new Uint8Array(buf))// res.value = new Buffer(arr.slice(3, buf.length - 5))var dataBuffer = buf.subarray(3, buf.length - 2)res.value = Array.prototype.slice.call(new Uint8Array(buf))}return res
}function crc16modbus(buf, previous) {var TABLE = [0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040];var crc = typeof previous !== 'undefined' ? ~~previous : 0xffff;for (var index = 0; index < buf.length; index++) {var byte = buf[index];crc = (TABLE[(crc ^ byte) & 0xff] ^ crc >> 8) & 0xffff;}return crc;
}function makeDataPacket(transId, protoId, unitId, funcCode, address, data, length) {if (typeof (data) == "boolean" && data) { data = 1 }if (typeof (data) == "boolean" && !data) { data = 0 }if (address == 0) { address = 65535 }else { address = address - 1 }var dataBytes = 0if (funcCode == 15) { dataBytes = length }if (funcCode == 16) { dataBytes = length * 2 }var bufferLength = 12if (funcCode == 15 || funcCode == 16) { bufferLength = 13 + dataBytes }var byteCount = bufferLength - 6var buf = new Buffer(bufferLength)buf.writeUInt16BE(transId, 0)buf.writeUInt16BE(protoId, 2)buf.writeUInt16BE(byteCount, 4)buf.writeUInt8(unitId, 6)buf.writeUInt8(funcCode, 7)buf.writeUInt16BE(address, 8)if (funcCode == 1 || funcCode == 2 || funcCode == 3 || funcCode == 4) {buf.writeUInt16BE(length, 10)}if (funcCode == 5 || funcCode == 6) {buf.writeInt16BE(data, 10)}if (funcCode == 15 || funcCode == 16) {buf.writeInt16BE(length, 10)buf.writeUInt8(dataBytes, 12)buf.writeInt32BE(data, 13)}var makeCrc = crc16modbusvar bufRtu = buf.slice(6, bufferLength)var crc = makeCrc(bufRtu)var arr = Array.prototype.slice.call(new Uint8Array(bufRtu))arr.push(0);arr.push(0);var buffRtu = new Buffer(arr);buffRtu.writeUInt16LE(crc, buffRtu.length - 2)//console.log('buffRtu:', buffRtu);return { rtu: Array.prototype.slice.call(new Uint8Array(buffRtu)) }
}function parseAddress(address) {var rtn = {}address = address.toLowerCase()// 提取地址// Data Type                  Short Hand   Size        Accessibility// Descrite Input             i            1 Bit       Read Only// Coil                       c            1 Bit       Read / Write// Input Register             ir           16 Bits     Read Only// Holding Register           hr           16 Bits     Read / Writevar isRegister = address.replace('r', '').length !== address.length;if (isRegister) {rtn.address = address.substr(2)rtn.type = address.substr(0, 2)}if (!isRegister) {rtn.address = address.substr(1)rtn.type = address.substr(0, 1)}var isRange = rtn.address.replace('-', '').length !== rtn.address.lengthif (isRange) {var range = rtn.address.split('-')rtn.length = range[0] - range[1]if (rtn.length < 0) { rtn.address = range[0] }if (rtn.length > 0) { rtn.address = range[1] }rtn.length = Math.abs(rtn.length) + 1}if (!isRange) {rtn.length = 1}rtn.address = parseInt(rtn.address)// 获取类型// FC1 - Read Coil// FC2 - Read Input// FC3 - Read Holding Registers// FC4 - Read Input Registers// FC5 - Write Single Coil// FC6 - Write Single Register// FC15 - Write Multiple Coils// FC16 - Write Multiple Registersif (rtn.type == 'c') {rtn.fcRead = 1rtn.fcWrite = 5}if (rtn.type == 'i') {rtn.fcRead = 2}if (rtn.type == 'hr' && !isRange) {rtn.fcRead = 3rtn.fcWrite = 6}if (rtn.type == 'hr' && isRange) {rtn.fcRead = 3rtn.fcWrite = 16}if (rtn.type == 'ir') {rtn.fcRead = 4}return rtn
}function Serial(uartPort, dirPort) {var rtn = {}var Uart = require('uart')rtn.port = Uart.open(uartPort)if (dirPort) {var events = require('events');var event = new events();var Gpio = require('gpio')var option = {};option.id = dirPort.id;rtn.io = Gpio.open(option);}rtn.send = function (data) {rtn.io.writeValue(dirPort.polarity === 0 ? 0 : 1);rtn.port.write(data)event.emit('send')}rtn.onData = function () { }rtn.port.on('data', function (data) {console.log("rtn onData");rtn.onData(data);})event.on('send', function () {rtn.io.writeValue(dirPort.polarity === 0 ? 1 : 0);})return rtn
}module.exports = Modbus;
app.json{"version": "1.0.0","io": {"UART2": {"type": "UART","port": 2,"dataWidth": 8,"baudRate": 9600,"stopBits": 1,"flowControl": "disable","parity": "none"},"D13": {"type": "GPIO","port": 33,"dir": "output","pull": "pulldown"}},"debugLevel": "DEBUG","repl": "disable"}

JavaScript使用Modbus协议实现RTU设备连云相关推荐

  1. java借助modbus协议实现与设备的通讯,收发信息,实现对设备信息的采集

    2018-07-27  4tr  转自 会飞的李小浩 修改微信分享: 扫盲:什么是modbus? Modbus是由Modicon(现为施耐德电气公司的一个品牌)在1979年发明的,是全球第一个真正用于 ...

  2. 基于.net 基于ModBus协议的PLC设备数据采集(单片机,研华6017设备)

    1.场景 项目上需要对一些工厂设备状态进行实时状态分析,生成折线图并报警等. 设备外面一般都接入了处理模块(单片机,6017等)(相当于网关设备),对信号进行转化,由网线接出,可进行采集. 2.程序 ...

  3. 关于winform串口程序(二)数据的发送(modbus协议RTU模式)

    串口项目使用的协议为Modbus,简介什么的我就不在网络上面班门弄斧了,下面就介绍一下Modbus发送指令的格式,以及我对数据的处理. 关于Modbus的数据传输如下: Modicon 控制器上的标准 ...

  4. Modbus协议在串行链路上的实现

    目录 1.串行链路通信简介 2.串行链路通信协议原理 3.串行链路通信帧描述 4.RTU.ASCII串行传输模式 4.1.RTU传输模式 4.2.ASCII传输模式 1.串行链路通信简介 Modbus ...

  5. STM32 —— Modbus 协议

    STM32 -- Modbus 协议 Modbus 协议简介 Modbus 是一种串行通信协议,由于其协议简单易用,且没有版权要求,目前已经成为工业领域通信协议的实时标准.ModBus 协议是又施耐德 ...

  6. Modbus协议介绍

    Modbus协议介绍 简介 Modbus是一种串行通信协议,是Modicon公司(现在的施耐德电气Schneider Electric)于 1979年为使用可编程逻辑控制器(PLC)通信而发表.Mod ...

  7. 协议篇之Modbus协议入门

    目录 引言 Modbus协议介绍 1.Modbus协议是不是开源的,免费的? 2.怎么传输,有线还是无线? 3.Modbus的数据格式? 4.Modbus和RS485什么关系? 5.什么是主从机? 6 ...

  8. STM8单片机串口同时识别自定义协议和Modbus协议

      在单片机开发中,串口是最常用的和外界交换数据的渠道,要使用串口,那必不可少的就是通信协议,通信协议就是单片机和外界通信的语言,要想正常和其他设备正常交流,首先语言必须相通.   在实际开发过程中由 ...

  9. java modbus 规约_Modbus RTU的规约详细资料详解

    Modbus可编程控制器之间可相互通讯,也可与不同网络上的其他设备进行通讯,支撑网络有Modicon的Modbus和Modbus+工业网络.网络信息存取可由控制器内置的端口,网络适配器以及Modico ...

  10. Modbus教程| Modbus协议,ASCII和RTU帧,Modbus工作

    转载自:https://www.rfwireless-world.com/Tutorials/Modbus-Protocol-tutorial.html 这个Modbus教程涵盖了modbus协议基础 ...

最新文章

  1. 免费使用《Autorun病毒防御者》
  2. 分享Kali Linux 2017年第24周镜像文件
  3. 5G NGC — PCF 策略控制功能
  4. TF-IDF与余弦相似性的应用(三):自动摘要
  5. mysql二进制日志被删除无法启动_mysql二进制日志文件出错导致mysql服务无法启动...
  6. matlab常用的代码,matlab常用代码
  7. 织梦linux php版本,Linux下安装DedeCMS及安全设置
  8. 《Algorithms》Comparable 实现选择排序
  9. Java MVC 1.0规范开始进入公开评审阶段
  10. Java--工厂模式
  11. 小D课堂 - 零基础入门SpringBoot2.X到实战_第三节SpringBoot热部署devtool和配置文件自动注入实战_14、SpringBoot2.x使用Dev-tool热部署...
  12. go1.5源代码安装
  13. qt自定义qtablemodel实现改变item的背景色
  14. 求出字符串中大写字母,小写字母和数字的个数
  15. java isbn_JAVA ISBN计算问题。。简单JAVA编程
  16. 山寨小小军团开发笔记 之 GamePool
  17. 云上架构和传统IT架构有什么区别及优势?
  18. Unity3d中UGUI组件精简复盘(十九)ContentSizeFitter组件
  19. 特邀嘉宾-著名主持人李艾“每一次登台都是一次成长
  20. 【解决方案】SkeyeVSS无线监测视频监控系统在有限空间作业中的保障应用

热门文章

  1. 苹果计算机格式化磁盘,苹果电脑怎么格式化
  2. 运用matlab求黑塞矩阵,用matlab求黑塞矩阵
  3. 计算机中文无敌版,与电脑下象棋无敌版
  4. Deepin上安装USB无线网卡驱动
  5. java连接sybase的pom_SpringBoot下多数据源连接Sybase数据库
  6. 别找了,这就是你心心念念想要的年会活动抽奖软件
  7. 形如1/(a+bsinx)的积分公式的证明
  8. Android 测试点归纳总结
  9. 亚马逊 kindle 刷机 过程记录
  10. Uniapp IM即时通讯 - GoEasy集成私聊和群聊