目录

前言

驱动目的

适用范围

使用示例

驱动源码

驱动解析


前言

Modbus协议是一种已广泛应用于当今工业控制领域的通用通讯协议。通过此协议,控制器相互之间、或控制器经由网络(如以太网)可以和其它设备之间进行通信。Modbus协议使用的是主从通讯技术,即由主设备主动查询和操作从设备。一般将主控设备方所使用的协议称为Modbus Master,从设备方使用的协议称为Modbus Slave。典型的主设备包括工控机和工业控制器等;典型的从设备如PLC可编程控制器等。

Modbus TCP/IP协议,去掉了Modbus协议本身的CRC校验,增加了MBAP 报文头。TCP/IP上的Modbus的请求/响应。

驱动目的

将该类型的控制器的相关监测数据对接至IOTOS的线上中台

适用范围

Wheelers的控制器

使用示例

  • 连接设备

将设备的电源插上,听到嘀嘀嘀的声音后表面设备正常启动,然后将网线一端插入到设备的网口,一端插入到电脑的网口

  • 访问设备

打开电脑的更改适配器选项

找到刚才插入的网口的网卡 ,右键属性,更改其IP地址,使得与控制器在一个网段且IP不一样。

这里该控制器的IP为192.168.11.111,所以将自己电脑的IP改为11网段的即可

更改完IP后打开cmd,ping控制器的IP如果可以ping则说明 可以访问到控制器

  • 中台操作

这里只说明了大致的操作流程,具体细节可以参考中台中台文档手册

首先在IOTOS中台创建网关,再打开的界面填写名称后点击确认即可创建成功

网关创建成功后去[我的模板]进行模板的创建

模板的内容如下:

创建完成后再去创建设备实例

选择刚刚创建的网关和模板,点击确认即可创建成功

最后去创建数据点,删除自带的四个数据点然后点击创建数据点,填写名称,选择类型。

然后点击高级配置,填写需要的参数

 这样批量读取后,读取几个后面的数据点就要创建几个。

然后其他十二个的配置为

也可以进行单个量的读取,修改其配置即可

  • SDK运行驱动

配置完后,在SDK目录下的_driver路径下新建一个名为dr_modbus_tcp的py文件,若路径下已有则不用再创建,其文件内容如下一节源码内容,然后在_example创建一个运行脚本.bat文件,内容如下:

创建完成后双击运行即可看到数据已经上报

至此控制器已经对接完成

驱动源码

# -*- coding:utf-8 -*-
# author : jiji time 12/10/2021
# Modbus tcp server
import sys
import modbus_tk.modbus_tcp as modbus_tcp
from modbus_tk.exceptions import ModbusInvalidResponseError
reload(sys)
sys.setdefaultencoding('utf8')sys.path.append("..")
from driver import *# 补码转为负数
def Complement2Negative(int_data):data = '0b'bin_data = bin(int_data).split('0b')[1]print bin(int_data)if len(bin_data) < 16:return int_dataelse:for i in bin_data:if i == '1':data += '0'if i == '0':data += '1'return (int(data,2)+1)*-1class ModbusTCPDriver(IOTOSDriverI):#1、通信初始化def InitComm(self,attrs):self._HOST = self.sysAttrs['config']['param']['HOST']self._PORT = self.sysAttrs['config']['param']['PORT']self._master = modbus_tcp.TcpMaster(host=self._HOST, port=self._PORT)self._master.set_timeout(5.0)self.online(True)self.setPauseCollect(False)self.setCollectingOneCircle(False)# #2、采集引擎回调,可也可以开启,也可以直接注释掉(对于主动上报,不存在遍历采集的情况)def Collecting(self, dataId):try:cfgtmp = self.data2attrs[dataId]['config']# 过滤非modbus tcp配置的点if not cfgtmp.has_key('param') or not cfgtmp.has_key('proxy'):return ()# 当是新一组功能号时;当没有proxy.pointer,或者有,但是值为null时,就进行采集!否则(有pointer且值不为null,表明设置了采集代理,那么自己自然就被略过了,因为被代理了)当前数据点遍历轮询会被略过!if 'pointer' not in cfgtmp['proxy'] or cfgtmp['proxy']['pointer'] == None or cfgtmp['proxy']['pointer'] == '':# 某些过滤掉不采集,因为有的地址的设备不在线,只要在proxy下面配置disabled:true,这样就不会轮训到它!if 'disabled' in cfgtmp['proxy'] and cfgtmp['proxy']['disabled'] == True:return ()else:self.warn(self.name(dataId))# 过滤非modbus rtu配置的点if not cfgtmp['param'].has_key('funid'):return ()# 功能码funid = cfgtmp['param']['funid']# 设备地址devid = cfgtmp['param']['devid']# 寄存器地址regad = cfgtmp['param']['regad']# 格式format = cfgtmp['param']['format']# 长度quantity = re.findall(r"\d+\.?\d*", format)if len(quantity):quantity = int(quantity[0])else:quantity = 1if format.lower().find('i') != -1:  # I、i类型数据为4个字节,所以n个数据,就是4n字节,除一般应对modbus标准协议的2字节一个数据的个数单位!quantity *= 4 / 2elif format.lower().find('h') != -1:quantity *= 2 / 2elif format.lower().find('b') != -1:quantity *= 1 / 2elif format.find('d') != -1:quantity *= 8 / 2elif format.find('f') != -1:quantity *= 4 / 2elif format.find('?') != -1:  # 对于功能号1、2的开关量读,开关个数,对于这种bool开关型,个数就不是返回字节数的两倍了!返回的字节个数是动态的,要字节数对应的位数总和,能覆盖传入的个数数值!quantity *= 1format = ''  # 实践发现,对于bool开关型,传入开关量个数就行,format保留为空!如果format设置为 "?"或"8?"、">?"等,都会解析不正确!!self.debug('>>>>>>' + '(PORT-' + str(self._PORT) + ')' + str(devid) + ' ' + str(funid) + ' ' + str(regad) + ' ' + str(quantity) + ' ' + str(format))rtu_ret = self._master.execute(devid, funid, regad, quantity, data_format=format)self.debug(rtu_ret)# 私有modbus解析if cfgtmp['param'].has_key('private'):# 温湿度传感器if cfgtmp['param']['private'] == 'Temp&Hum':data_list = []for i in rtu_ret:data_list.append(Complement2Negative(i)*0.1)rtu_ret = tuple(data_list)if cfgtmp['param']['private'] == 'time':#     wheelers表的时间的解析rtu_ret = str(rtu_ret[0]) + "年" + str(rtu_ret[1]) + "月" + str(rtu_ret[3]) + "日" + str(rtu_ret[4]) + "时" + str(rtu_ret[5]) + "分" + str(rtu_ret[6]) +"秒"return (rtu_ret,)return rtu_retexcept ModbusInvalidResponseError, e:self.error(u'MODBUS响应超时, ' + e.message)return Noneexcept Exception, e:traceback.print_exc(e.message)self.error(u'采集解析参数错误:' + e.message)return Nonedef Event_setData(self, dataId, value):# self.setValue(self.name(dataId),value)return json.dumps({'code': 0, 'msg': '', 'data': ''})

驱动解析

  • 导入相关的包,包括Modbus Tcp连接所需要的包和iotos运行驱动的依赖包
# -*- coding:utf-8 -*-
# Modbus tcp server
import sys
import modbus_tk.modbus_tcp as modbus_tcp
from modbus_tk.exceptions import ModbusInvalidResponseError
reload(sys)
sys.setdefaultencoding('utf8')sys.path.append("..")
from driver import *
  • 通讯初始化,定义驱动需要运行的类并将其初始化,获取中台配置的IP和端口并进行TCP的连接
class ModbusTCPDriver(IOTOSDriverI):#1、通信初始化def InitComm(self,attrs):self._HOST = self.sysAttrs['config']['param']['HOST']self._PORT = self.sysAttrs['config']['param']['PORT']self._master = modbus_tcp.TcpMaster(host=self._HOST, port=self._PORT)self._master.set_timeout(5.0)self.online(True)self.setPauseCollect(False)self.setCollectingOneCircle(False)
  • 编写采集函数。获取中台数据点的配置,然后通过已连接的Tcp用数据点里面的配置向控制器发生命令,得到返回值后进行数据点的赋值
    # #2、采集引擎回调,可也可以开启,也可以直接注释掉(对于主动上报,不存在遍历采集的情况)def Collecting(self, dataId):try:cfgtmp = self.data2attrs[dataId]['config']# 过滤非modbus tcp配置的点if not cfgtmp.has_key('param') or not cfgtmp.has_key('proxy'):return ()# 当是新一组功能号时;当没有proxy.pointer,或者有,但是值为null时,就进行采集!否则(有pointer且值不为null,表明设置了采集代理,那么自己自然就被略过了,因为被代理了)当前数据点遍历轮询会被略过!if 'pointer' not in cfgtmp['proxy'] or cfgtmp['proxy']['pointer'] == None or cfgtmp['proxy']['pointer'] == '':# 某些过滤掉不采集,因为有的地址的设备不在线,只要在proxy下面配置disabled:true,这样就不会轮训到它!if 'disabled' in cfgtmp['proxy'] and cfgtmp['proxy']['disabled'] == True:return ()else:self.warn(self.name(dataId))# 过滤非modbus rtu配置的点if not cfgtmp['param'].has_key('funid'):return ()# 功能码funid = cfgtmp['param']['funid']# 设备地址devid = cfgtmp['param']['devid']# 寄存器地址regad = cfgtmp['param']['regad']# 格式format = cfgtmp['param']['format']# 长度quantity = re.findall(r"\d+\.?\d*", format)if len(quantity):quantity = int(quantity[0])else:quantity = 1if format.lower().find('i') != -1:  # I、i类型数据为4个字节,所以n个数据,就是4n字节,除一般应对modbus标准协议的2字节一个数据的个数单位!quantity *= 4 / 2elif format.lower().find('h') != -1:quantity *= 2 / 2elif format.lower().find('b') != -1:quantity *= 1 / 2elif format.find('d') != -1:quantity *= 8 / 2elif format.find('f') != -1:quantity *= 4 / 2elif format.find('?') != -1:  # 对于功能号1、2的开关量读,开关个数,对于这种bool开关型,个数就不是返回字节数的两倍了!返回的字节个数是动态的,要字节数对应的位数总和,能覆盖传入的个数数值!quantity *= 1format = ''  # 实践发现,对于bool开关型,传入开关量个数就行,format保留为空!如果format设置为 "?"或"8?"、">?"等,都会解析不正确!!self.debug('>>>>>>' + '(PORT-' + str(self._PORT) + ')' + str(devid) + ' ' + str(funid) + ' ' + str(regad) + ' ' + str(quantity) + ' ' + str(format))rtu_ret = self._master.execute(devid, funid, regad, quantity, data_format=format)self.debug(rtu_ret)# 私有modbus解析if cfgtmp['param'].has_key('private'):# 温湿度传感器if cfgtmp['param']['private'] == 'Temp&Hum':data_list = []for i in rtu_ret:data_list.append(Complement2Negative(i)*0.1)rtu_ret = tuple(data_list)if cfgtmp['param']['private'] == 'time':#     wheelers表的时间的解析rtu_ret = str(rtu_ret[0]) + "年" + str(rtu_ret[1]) + "月" + str(rtu_ret[3]) + "日" + str(rtu_ret[4]) + "时" + str(rtu_ret[5]) + "分" + str(rtu_ret[6]) +"秒"return (rtu_ret,)return rtu_retexcept ModbusInvalidResponseError, e:self.error(u'MODBUS响应超时, ' + e.message)return Noneexcept Exception, e:traceback.print_exc(e.message)self.error(u'采集解析参数错误:' + e.message)return None
  • 编写下发函数。也可以不定义,定义后可以用于中台数据点的下发
    def Event_setData(self, dataId, value):# self.setValue(self.name(dataId),value)return json.dumps({'code': 0, 'msg': '', 'data': ''})

IOTOS物联中台Modbus_Tcp驱动对接Wheelers控制器设备相关推荐

  1. IOTOS物联中台modbus驱动对接雅达电表设备

    本文章为原创,转载请注明出处! 登录平台:IOTOS®爱投斯物联中台 账号:iotos_test    密码:iotos123 代码地址:IOTOSDK-Python: IOTOS Python版本S ...

  2. IOTOS物联中台modbus驱动对接科士达精密空调设备

    本文章为原创,转载请注明出处! 登录平台:IOTOS®爱投斯物联中台 账号:iotos_test    密码:iotos123 代码地址:IOTOSDK-Python: IOTOS Python版本S ...

  3. IOTOS物联中台开发驱动支持NB-IoT光电感烟火灾探测报警器设备

    本文章为原创,转载请注明出处! 登录平台:IOTOS®爱投斯物联中台 账号:iotos_test    密码:iotos123 代码地址:IOTOSDK-Python: IOTOS Python版本S ...

  4. IOTOS物联中台开发驱动支持中安易科智能门锁API 详解

    本文章为原创,转载请注明出处! 登录平台:IOTOS®爱投斯物联中台 账号:iotos_test    密码:iotos123 代码地址:IOTOSDK-Python: IOTOS Python版本S ...

  5. IOTOS物联中台Bacnet驱动开发实例

    本文章为原创,转载请注明出处! 登录平台:IOTOS®爱投斯物联中台 账号:iotos_test    密码:iotos123 代码地址:IOTOSDK-Python: IOTOS Python版本S ...

  6. IOTOS物联中台非标modbus驱动对接易事特UPS电源设备

    本文章为原创,转载请注明出处! 登录平台:IOTOS®爱投斯物联中台 账号:iotos_test    密码:iotos123 代码地址:IOTOSDK-Python: IOTOS Python版本S ...

  7. IOTOS物联中台从0到1开发modbus_rtu驱动 实例详解

    本文章为原创,转载请注明出处! 登录平台:IOTOS®爱投斯物联中台 账号:iotos_test    密码:iotos123 代码地址:IOTOSDK-Python: IOTOS Python版本S ...

  8. ESP8266 贝壳物联

    小白10元玩转智能家居使用天猫精灵+ESP8266WiFi模块对接贝壳物联,可以OLED 屏幕显示温湿度并上传服务器,WiFi控制小车等一系列智能产品 2019-03-24 10:38:17 昂好多个 ...

  9. 如何用smardaten90天快速开发并上线智慧空间loT物联平台?

    前言 大家好,我是小白白,前段时间一位好友接手了一个"烫手山芋"开发任务,77万㎡的科技园区需要打造智慧空间物联平台.要求接入600+园区设备,处理15000+日数据量,在打造整体 ...

最新文章

  1. 决策树算法python源代码_决的解释|决的意思|汉典“决”字的基本解释
  2. 【错误记录】Android 分区存储 错误 ( 文件格式不匹配 )
  3. 使用log4jdbc记录SQL信息
  4. 内存溢出_JVM|03内存溢出实战
  5. Django中models利用ORM对Mysql 进行查表的语句(多个语句)
  6. Fiddler 学习笔记---命令、断点
  7. Enterprise Vault 10.0.4 FOR Exchange2013 部署之三-日记邮件归档
  8. 渲染完毕再渲染数据_三星Galaxy S21渲染图再曝:多种配色、新设计
  9. Android 颜色渲染(三) Shader颜色渲染
  10. MyEclipse 2014 之 安装JDK 7 与JRE 7 (二)
  11. python打印图像所有的像素值
  12. GO语言 使用hash 表
  13. windows DNS污染解决
  14. 入门推荐系统,这25篇综述文章足够了
  15. xp计算机能装win系统吗,自己用的电脑要装系统,XP, Win7, Win10到底选哪个?解救小白篇...
  16. 大牛耗时一年最佳总结,让你的app体验更丝滑!震撼来袭免费下载!
  17. 跳动的心html5,施华洛世奇跳动的心真假怎么分辨
  18. 自定义控件三部曲之动画篇(七)——ObjectAnimator基本使用
  19. Android程序员如何高薪接私活?十年老炮告诉你,看这一篇就够了
  20. 使用阿里云短信服务API实现短信验证码以及短信服务通知

热门文章

  1. Word英文字体的小型大写字母样式
  2. 如何订制个性化的网址导航
  3. 大数据在智慧城市中的应用
  4. Java封装如何封装 封装的好处是什么?
  5. MySQL基础操作增,删,改,查。
  6. 志宇-RabbitMQ学习
  7. 计算机还原默认的配置,每次启动电脑,bios都会恢复默认设置怎么办?
  8. 医学影像三维可视化软件
  9. three.js,透明模型能够遮挡可见模型
  10. 使用C语言实现接水问题