本文讲解4.2版jxTMS如何用数据源访问modbus设备,整个系列的文章请查看:docker版jxTMS使用指南:4.2版升级内容
docker版本的使用,请参考docker版jxTMS使用指南
4.0版jxTMS的说明,请查看:4.0版升级内容
在docker镜像的/home/tms/python/app/module/目录下,笔者提供了dataSource_modbus.py文件,该文件就实现了用modbus来拉取数据。看完大家会发现,数据源和modbus的结合,简直简单到了极点。
继承自数据源的dataSource_modbus使用modbus_tk来执行modbus操作,核心就做了四件事:
1、初始化modbus连接:
self._master = modbus_tcp.TcpMaster(ip, port)
2、重载pull函数:
def pull(self, t):
#从机地址
s = t[2]
#功能码
f = t[3]
#希望访问的寄存器号
r = t[4]
#希望访问的数量
n = t[5]
try:
#读取寄存器
return self._master.execute(s, f, r, n)
except ConnectionRefusedError:
#失联
jxGo.log('warn',self._disConnectionMsg)
except:
pr = traceback.format_exc()
jxGo.log('warn',f'modbus pull [{t[0]}.{t[1]}] error:{pr}')
#执行到这里一定是出现了错误
if self._errorNum < 3:
#3次错误才动作
self._errorNum = self._errorNum + 1
else:
self._errorNum = 0
#错误不可避免,所以终止继续访问,等待下一个周期继续
self.clearWandQueue()
return None
3、增加一个start函数以封装setPullMode:
def start(self):
#延迟10秒后执行以分散处理压力
self.setPullMode(delayExec_seconds=10,
taskInterval_milliseconds=self._taskInterval_milliseconds,
interval_seconds=self._interval_seconds)
4、注册modbus类型的数据源:
def _newModbusDataSource(*args, **kw):
return dataSource_modbus(*args, **kw)
dataSource.register('modbus',_newModbusDataSource)
使用modbus数据源
注册后,在需要时执行下述命令即可:
self._dataSource = dataSource.New('modbus',afterPullDual=self._afterPull,
informDual=self._setData,ip=sp30h_ip,port=sp30h_port,
taskInterval_milliseconds=500,
interval_seconds=300)
在docker镜像的/home/tms/python/app/sinosoarSP30H/目录下的site.py文件中sp30h_slave站点就是如此定义了自己的数据源。
其指定了_afterPull函数来执行拉取到数据的后处理:
def _afterPull(self, t, tv):
if tv is None:
return None
#数据类型,在jxUtils中定义
dt = t[6]
#modbus读到的是一个元组
v = tv[0]
if dt == dataType_int16:
if v >= 32767:
#16位带符号整数
v = jxUtils.trans2short(v)
elif dt == dataType_uint32:
#32位无符号整数
v = jxUtils.trans2u32(v)
#缩放倍率【modbus的寄存器使用16位无符号数,精度可能不够,所以有时需要使用倍率来进行缩放】
rate = t[7]
if rate > 0:
return v * rate
return v
sp30h_slave还封装了数据源的addWantReceiveOver、addWantReceive两函数:
def addWantReceiveOver(self, dn, receiveFunc):
#为数据源支流添加访问入口
return self._dataSource.addWantReceiveOver(dn, receiveFunc)
def addWantReceive(self, dn, vn, slave, readFn, regid, num, dataType, rate, productStatement, compareStatement):
#为数据源支流添加访问入口
t = (dn,vn,slave,readFn,regid,num,dataType,rate)
self._dataSource.addWantReceive(t,productStatement=productStatement,compareStatement=compareStatement)
现在只需要添加待拉取的数据点即可。这部分代码在docker镜像的/home/tms/python/app/sinosoarSP30H/目录下的几个device文件中,都是根据设备厂家提供的产品手册查到需要的寄存器信息依次调用即可,大家根据注释读下代码就可以理解了。
注:可能有同学说,怎么好像没有定义数据策略呢?原因很简单,数据源中拉取到的数据,先是根据拉取参数元组中的dn【设备名】、vn【变量名】已经存放到dict中了,然后又经过afterDual将其转换为合适的数据格式和精度了,所以各设备接收到的数据就已经是符合要求的数据了,自然就不再需要数据策略进行解析和转换了
参考资料:
下面的系列文章讲述了如何用jxTMS开发一个实用的业务功能:
下面的系列文章讲述了jxTMS的一些基本开发能力: