CommManager Class
通讯管理器,传递查询语句和结果管理串口子线程的作用,封装了多线程,向外部提供统一的 接口,起到类似中介的作用,将 AbstractProtocol 和实际执行串口/网络访问的类(子线程中)聚合起来,方便迭代更新 More...
Public Functions
CommManager(QObject *parent = 0) | |
~CommManager() | |
AbstractComm * | abstractComm() const |
void | addProtocol(AbstractProtocol *p) |
const CommInfo & | currentCommInfo() |
void | delProtocol(AbstractProtocol *p) |
T | getProtocol(const QString &objectName) |
AbstractProtocol * | protocol(const QString &objectName) |
const QList<AbstractProtocol *> & | protocolList() |
void | removeAllProtocol() |
void | resetMode(const QString &type, const bool halfDuplex) |
void | resetMode(const QString &className) |
const CommState & | state() |
Public Slots
virtual void | close() |
virtual void | openDevice(const QString &name = "") |
virtual void | startNextQuery() |
virtual void | startQuery() |
virtual void | stopAllQuery() |
Signals
void | cmdCountChanged(const int remain, const int all) |
void | codeMayMessed() |
void | commInfoChanged(const CommInfo &ci) |
void | recvLineData(const QByteArray &data, const int count = 0) |
void | recvRawData(const QByteArray &data) |
void | sendData(const QByteArray &data) |
void | setCommProperty(const QString &key, const QVariant &value) |
void | stateChanged(const CommState &state) |
Protected Functions
void | init(const QString &name) |
Protected Slots
void | onRecvLineData(const QByteArray &data) |
void | onStateChanged(const CommState &state) |
void | onTimeout() |
void | onWriteFinish() |
void | write() |
Detailed Description
\author
BriFuture
通讯管理器,传递查询语句和结果管理串口子线程的作用,封装了多线程,向外部提供统一的 接口,起到类似中介的作用,将 AbstractProtocol 和实际执行串口/网络访问的类(子线程中)聚合起来,方便迭代更新
\date
2018.07.19 This is a new Communicator Class which doesn't exactly query and process data, because the real serialPort/socket is moved into a subThread which wont block UI-thread, it is a manager class that handle the sub thread, notify serial to query, receive data from serial port / network, and transfer it into BaseComm's implementation.
Warning: \date
2018.04.25
此前串口通讯无法正确识别下位机的发送时间间隔(数据每隔 16 ms 才被接收到)。最终在 FT232R 的驱动设置中找到了延时的根本原因 (参考http://projectgus.com/2011/10/notes-on-ftdi-latency-with-arduino/), 因此解决了串口通讯无法识别下位机发送时间间隙的问题。
Because of the delay of data coming into serial port (it is after almost 16ms that the data can be received from serial port), Finally, we found the root cause of the delay is made by the driver settings of FT232R with the help of this article: http://projectgus.com/2011/10/notes-on-ftdi-latency-with-arduino/ At last, we solved the problem of the data delay and successfully found the gap between tow sentences from slave computer.
example:
CommManager *cm = Comm::manager; cm.resetMode("Network", true); // 设为网络通讯半双工模式 connect(cm, &CommManager::recvLineData, this, &SomeClass::recvLine); // 接收数据
Member Function Documentation
CommManager::CommManager(QObject *parent = 0)
Default constructs an instance of CommManager.
CommManager::~CommManager()
关闭串口/网路,结束子线程
AbstractComm *CommManager::abstractComm() const
返回当前所用的通讯器
void CommManager::addProtocol(AbstractProtocol *p)
向 CommManager 管理器中添加协议,以便处理相应协议的数据
example:
CommManager *manager = Comm::manager; ... qDebug() << "List Size: " << manager.protocolList().size(); // assume the size now is N = 10, then output is "List Size: 10" AbstractProtocol *p = new ImplProtocol; // ImplProtocol must be implement subclass of AbstractProtocol manager->addProtocol(p); // now ImplProtocol is added, the data will be transmitted to this protocol if it is enabled. qDebug() << "List Size: " << manager.protocolList().size(); // output is "List Size: 11"
See also CommManager::onRecvLineData and CommManager::delProtocol.
[virtual slot]
void CommManager::close()
关闭串口并清空指令队列
example:
CommManager *m = Comm::manager; m->openDevice("COM1"); // 打开 COM1 串口 ... m->close(); // 关闭打开的 COM1 串口
[signal]
void CommManager::cmdCountChanged(const int remain, const int all)
通知其他组件指令数目有变化
[signal]
void CommManager::codeMayMessed()
[signal]
void CommManager::commInfoChanged(const CommInfo &ci)
const CommInfo &CommManager::currentCommInfo()
返回当前通讯器的 CommInfo \return
void CommManager::delProtocol(AbstractProtocol *p)
删除管理器中的协议
example:
CommManager *manager = Comm::manager; ... qDebug() << "List Size: " << manager.protocolList().size(); // assume the size now is N = 10, then output is "List Size: 10" manager->delProtocol(p); // p points to an instance of ImplProtocol qDebug() << "List Size: " << manager.protocolList().size(); // output is "List Size: 9"
See also CommManager::addProtocol.
T CommManager::getProtocol(const QString &objectName)
[protected]
void CommManager::init(const QString &name)
将 mode 字符串传递给负责构造 AbstractComm 的工厂类。 Pass the mode string into CommFactory::defaultFactory() that responds for construct BaseComm @param mode
[protected slot]
void CommManager::onRecvLineData(const QByteArray &data)
接收到来自串口的数据后,将其转发给各个协议
[protected slot]
void CommManager::onStateChanged(const CommState &state)
在设备的状态改变时,将状态转发给其它层
[protected slot]
void CommManager::onTimeout()
[protected slot]
void CommManager::onWriteFinish()
在实际串口执行完查询后进行相应操作
@date 2018.06.16 可能存在的bug: 假设查询队列为 Q1, Q2, Q3 回复为 A1, A2 A3, A4 这里的 A2 A3 是在查询完 Q2 之后同时回复 然而此时协议的定时器尚未工作,在接收到 A3 回复时由于定时器发生错误导致查询队列(程序)崩溃, 因此协议在接收指令时务必判断定时器是否工作
[virtual slot]
void CommManager::openDevice(const QString &name = "")
打开指定设备,若参数 name 为空,则默认打开最后一次使用的设备
example: 打开串口 COM1
CommManager *manager = Comm::manager; manager->openDevice("COM1"); // if serial port COM1 is free to use, then COM1 will be occupied by the program
连接服务器 192.168.0.100 / localhost,连接网络前需要设置端口
manager->setCommProperty("port", 8080); manager->openDevice("localhost"); // connect to localhost // manager->openDevice("192.168.0.100"); // effects the same as before
See also CommManager::setCommProperty and CommManager::close.
AbstractProtocol *CommManager::protocol(const QString &objectName)
const QList<AbstractProtocol *> &CommManager::protocolList()
[signal]
void CommManager::recvLineData(const QByteArray &data, const int count = 0)
[signal]
void CommManager::recvRawData(const QByteArray &data)
通知其他组件从串口/网络中接收到的原始数据(即不一定包含 AbstractProtocol::LineSeperator 的数据)
void CommManager::removeAllProtocol()
void CommManager::resetMode(const QString &type, const bool halfDuplex)
CommManager::resetMode
This is an overloaded function.
example:
... manager->resetMode("Network", false); //设为网络通讯全双工模式s
void CommManager::resetMode(const QString &className)
指定的className,重设Comm模式 提供该接口是为了在某些特殊情况下,现有的通讯器无法满足要求,需要扩展通讯器时,通过该方法生成自定义的通讯器类
This is an overloaded function.
扩展通讯器示例:
Comm::factory->addComm(SubComm::staticMetaObject, SubComm::commInfo); // SubComm is a subclass of Abstract Comm Comm::manager->resetMode("SubComm"); // 构建一个新的通讯器
common example:
// assume that there is a communicator VirtualCom OTHER THAN ComFullDuplex CommManager *manager = Comm::manager; ... manager->resetMode("VirtualCom"); // Data will be received from VirtualCom
See also CommFactory and CommManager::resetMode(const QString &type, const bool halfDuplex).
[signal]
void CommManager::sendData(const QByteArray &data)
表示数据已经由通讯器发送到串口/网络中
[signal]
void CommManager::setCommProperty(const QString &key, const QVariant &value)
设置串口/网络设备的属性
See also AbstractComm::setCommProperty.
[virtual slot]
void CommManager::startNextQuery()
若协议中有指令未执行,接着执行下一条指令
[virtual slot]
void CommManager::startQuery()
发送的指令可能不会立即被下位机执行,需要等待一定时间接收下位机的反馈。
example
... manager->startQuery(); // 从协议列表中找出一个用命令的协议,将该命令写入到串口等设备中进行查询
const CommState &CommManager::state()
返回串口状态
[signal]
void CommManager::stateChanged(const CommState &state)
通知串口/网络设备的状态有变化
[virtual slot]
void CommManager::stopAllQuery()
停止所有查询,并通知协议管理器也重置查询