1.  抽象协议AbstractProtocol

抽象协议AbstractProtocol定义CommManager与协议之间的接口。AbstractProtocol中的一些属性(如enabled)用于设置是否能够处理数据。

processData是AbstractProtocol中定义的回调函数,当设备中有数据返回时,数据将会被交给该方法进行处理。

若该方法返回true,则表明当前处理数据的协议已经找到相应的数据并且不需要将数据再交给其它协议处理,CommManager便会停止向其它协议发送这些数据;

若该方法返回为false,表明当前处理数据的协议并未找到相应的数据,并且希望交由其它协议进行处理,此时Com会继续转发这些数据。

lastQueryFailed 是在查询失败时由协议实现类进行处理的回调函数。

AbstractProtocol(生产者)实例将会维护各自的命令队列,CommManager(消费者)在完成一次查询后拉取AbstractProtocol(生产者)生成的指令。因此CommManager会根据指令消耗的速度决定是否应该进行下一次查询。有关生产者和消费者的更多信息,可以查看 https://www.cnblogs.com/charlesblc/p/6045238.html

2.  通讯器构造工厂

CommFactory是通讯器的构造工厂类,要实例化某个AbstractComm的通讯器实现类,需要通过addComm方法将通讯器注册到CommFactory中,工厂会保存各个通讯器的实现类对象,在构造之后进行切换会尝试找出已经构造过的对象,避免重复构造通讯器对象。

CommManager中可用的串口实现类对象由CommFactory进行例化,通过createComm方法将参数传递给工厂类的实例化方法,获取可用的实现类对象指针。

Comm层作为库,暴露给其它代码使用的部分主要是CommManager,因此要在程序运行时改变串口工作模式或切换成网络接口,调用 CommManager::resetMode 方法即可。

若该模块内部已经有实现好的通讯器,则可以调用 CommManager::resetMode(const QString &type, const bool halfDuplex),根据类型和全/半双工模式选择特定的通讯器,若要使用扩展的自定义通讯器,可以使用 CommManager::resetMode(const QString &className) 传入具体的类名选择通讯器。

如果需要添加新的通讯器,创建一个继承于AbstractComm的子类(构造函数需要用Q_INVOKABLE修饰),通过addComm方法将元对象和描述信息添加到工厂类中,之后可以传递类名来构造其它的通讯器。

构造工厂的使用使得CommManager只用传递类名或通讯器类型即可获得通讯器对象,从而使CommManager的功能只需要对通讯器对象进行管理和收发数据,简化CommManager 的实现。

3.  虚拟串口示例(待完善)

虚拟串口VirtualCom是为了方便上位机单独进行调试而编写的AbstractCom的子类。以虚拟串口为例,介绍如何继承实现AbstractCom的子类,以设计新模式的串口。

虚拟串口VirtualCom的接口:

如图所示,VirtualCom的init(), close(), openComm, writeCmd, setCommProperty, query, onRead等方法都是继承自AbstractCom的接口(在方法声明后增加了 Q_DECL_OVERRIDE宏,即override 关键字)。

init()方法中进行成员变量的初始化(多线程中的QIODevice只能在创建其实例的线程中进行操作,否则在运行时会警告/报错),需要在该方法中可以实例化QTimer,QSerialPort或QTcpSocket等对象(这些对象不能在构造函数中实例化)。

虚拟串口中没有使用到串口对象,因此不需要实例化串口/QIODevice对象,这里的init方法中实例化timer对象并连接相应的信号和槽。

openComm方法用于打开设备(串口/Socket),由于虚拟串口中没有串口对象,这里只修改设备状态即可。打开虚拟串口后,timer开始计时。

打开串口后即可调用write写入命令:一般该方法只需要传递参数给query函数执行即可,但半双工模式下,需要保存指令,待线路空闲时发送。

若接受到命令后可以立即查询,那么需要通过QMetaObject::invokeMethod静态方法在子线程中运行(以致访问串口/Socket对象时不会出现错误)。虚拟串口中的该方法就是将cmd参数传递给query方法通过子线程执行。

要使用虚拟串口发送一些特定的数据,需要修改VirtualCom的实现,在实际使用过程中比较麻烦。目前可用的解决方法有两个:

  1. 把虚拟串口编译成动态链接库,在不同的程序中使用不同的动态库文件即可,但是这样做实际上在开发过程中变得非常麻烦。
  2. 自定义xml文件格式,从指定的xml文件中读取信息,根据信息来决定发送的数据内容,这样的话就能够使VirtualCom作为库文件与实际的信息回复实现分离。如果要这样实现,首先要定义xml文件的格式,然后编写相应的解析器,并将解析器解析的结果传递给VirtualCom对象,当接收到来自上层的指令后根据解析器的结果进行响应。这样做实际上是在模拟下位机收发数据的行为,看上去工作量较大,但比较实际的下位机应用应该是简单不少了。

自定义Qt组件-通讯模块(P2)的更多相关文章

  1. 自定义Qt组件-通讯模块(P1)

    通讯模块Communicator 通讯模块是整个项目设计中位于最底层的模块,用于处理与串口或网络等设备的通讯,所有设备的通讯通过CommManager类完成,上层软件设计时需要根据comm模块(主要是 ...

  2. 自定义Qt组件-通讯模块(P3)

    1.   半双工模式实时检测串口 ComHalfDuplex类是为了解决上位机发送控制指令和下位机发送数据会在半双工RS485总线中产生冲突引起乱码而引入的(v0.010版本引入). 解决冲突的原理主 ...

  3. C/C++ Qt TableDelegate 自定义代理组件

    TableDelegate 自定义代理组件的主要作用是对原有表格进行调整,例如默认情况下Table中的缺省代理就是一个编辑框,我们只能够在编辑框内输入数据,而有时我们想选择数据而不是输入,此时就需要重 ...

  4. SSIS自定义数据流组件开发(血路)

    由于特殊的原因(怎么特殊不解释),需要开发自定义数据流组件处理. 查了很多资料,用了不同的版本,发现各种各样的问题没有找到最终的解决方案. 遇到的问题如下: 用VS2015编译出来的插件,在SSDTB ...

  5. Android Studio开发基础之自定义View组件

    一般情况下,不直接使用View和ViewGroup类,而是使用使用其子类.例如要显示一张图片可以用View类的子类ImageView,开发自定义View组件可分为两个主要步骤: 一.创建一个继承自an ...

  6. [UE4]自定义MovementComponent组件

    自定义Movement组件 目的:实现自定义轨迹如抛物线,线性,定点等运动方式,作为组件控制绑定对象的运动. 基类:UMovementComponent 过程: 1.创建UCustomMovement ...

  7. Qt组件中的双缓冲无闪烁绘图

      双缓冲绘图在Qt4中,所有的窗口部件默认都使用双缓冲进行绘图.使用双缓冲,可以减轻绘制的闪烁感.在有些情况下,用户要关闭双缓冲,自己管理绘图.下面的语句设置了窗口部件的Qt::WA_PaintOn ...

  8. 【转】Android学习基础自定义Checkbox组件

    原文网址:http://forum.maiziedu.com/thread-515-1-1.html heckbox组件是一种可同时选中多项的基础控件,即复选框,在android学习中,Checkbo ...

  9. 自定义Qt按钮

    转自:http://blog.csdn.net/starcloud_zxt/article/details/5185556 Qt自带的PushButton样式比较单一,在开发的时候往往按钮的形状各异, ...

随机推荐

  1. html复杂url提交

    在使用手机向webapi发送照片请求的时候遇到一个问题,关于base64位字符串码无法识别,提交的表单是这样的: <form id="form1" method=" ...

  2. EIP权限工作流升级说明-2019/3/5

    首页增加待办事项直接处理按钮 2,新增处理历史记录

  3. JS万金油的类型判断方法

    Object.prototype.toString.call(data).slice(8, -1).toLowerCase();

  4. Unity自带IAP插件使用(googleplay)

    https://blog.csdn.net/ar__ha/article/details/64439872 Unity Services里的Unity IAP对于IOS和GooglePlay的支付用这 ...

  5. spring 和 mybatis 整合过程 (包含分页)

    1.spring-mybatis.xml  : 配置 SqlSessionFactory 和  MapperScannerConfigurer  <bean id="sqlSessio ...

  6. phantomjs截图中文网站网页页面乱码,安装字体解决

    用phantomjs去截取中文页面的网站可能会出现乱码的情况,也就是截图中中文的位置全是方框. 解决办法就是安装字体. 在centos中执行:yum install bitmap-fonts bitm ...

  7. 模板 ST表

    ST表 询问静态最值. code: #include <iostream> #include <cstdio> using namespace std; inline int ...

  8. arcgis10.0直连sde

  9. 2015苏州大学ACM-ICPC集训队选拔赛(2) 1001 1003 1010

    草爷要的榜 Problem Description 苏州大学代表队又勤奋地开始了训练.今天开了一场时长5小时的组队训练赛,苏州大学的n(1<=n<=100)支校队奋力拼(hua)搏(shu ...

  10. 10-排序6 Sort with Swap(0, i) (25 分)

    Given any permutation of the numbers {0, 1, 2,..., N−1}, it is easy to sort them in increasing order ...