modbustcp批量读取

之前写modbusrtu的数据采集都比较偷懒,用的最简单的每条报文只读取一个数据的方式。数据量小没什么问题

但是数据量大时,每次轮询要几十上百条通信报文,来来回回时间就耽误了。

这次遇到一个项目就是数据点表比较多,并且地址是连在一起的,这样就自然而然想到,把相邻的区间合并起来,共用一条报文。

这里我分了三步走。

第一步,解析输入的点表,点表主要两个参数,一个是节点地址,另一个是数据类型。

节点地址有不同格式,一种是标准的40001或者40001.1的格式,这种格式第一个字取值1234标记读哪段寄存器,而后面的数字就是数据地址了。根据数据类型不同,读取的长度有1或2个word。后面.1则是bool时,在这个word上的16个bit里,哪一个bit是这个变量。

另一种是施耐德的%mw %md等格式,这种格式是把数据类型附在前缀上,比如mw是一个字的int,md是两个子的int,但是实际点表配置也不一定沿用。

总之根据不同的逻辑,得到每个node的读取寄存器,偏移地址,读取长度。 拿到这个三元组,第一步完成。

第二步 合并相邻区域

这里参考以前算法题里的合并数组项。对于同一寄存器里的多个节点。我们根据偏移地址从小到大排序,然后从头遍历

对于第一个节点,生成一个查询语句,把节点加进去,然后到下一个节点时,判断该节点的偏移地址是不是跟在查询语句的结尾。是的话就可以把查询语句加长,同时把该节点加进该语句包含的元素里。不是的话我们就把这个查询语句和包含节点的二元组保存下来,然后对该节点,生成一个新的查询语句。

针对bool偏移量,这种偏移地址相同的,我们就不增加长度,但是还是把节点加进来。

这样我们就得到了查询语句。

调用modbus读取函数拿到数据,拿到数据后我们再依次读取查询语句里包含的节点,偏移量减去查询语句的偏移量,就能得到数据在结果数组的第几位,根据输入的data 类型做转换即可。


评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注