ãã¹ãŠã®äººã«è¯ãäžæ¥ãïŒ
æè¿ãäžçã®éãšéä¿¡ããããã®ãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãäœæãããšãããããªãèå³æ·±ãä»äºã«çŽé¢ããŸããã 圌女ãšã®éä¿¡ã¯ãCOMããŒããä»ããŠè¡ãããŸããã äœæ¥ã¯Windowsãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã®ãªã¢ã«ã¿ã€ã ã·ã¹ãã ïŒãããšåãããŒããŠã§ã¢ïŒã䜿çšããããšã«ãªã£ãŠãããããGUIã®é床ãäœäžããªãããã«ãããããCOMããŒãã䜿çšããäœæ¥ãå¥ã®ã¹ããªãŒã ã«å ¥ããããšã«ããŸããã ã·ã¹ãã èªäœã®èŠä»¶ã¯çµ¶ããå€åããŠãããããä¿®æ£ãæå°éã«æããé«éåããããã«ãMVPèšèšãã¿ãŒã³ã䜿çšããŠèšè¿°ããããšã決å®ããŸããã Qtãéçºç°å¢ãšããŠéžæãããŸããã ç§ã¯ãã®åªäœãšãã®æ©èœã奜ãã ããã§ãã ããã§ãQt + MVP + Qthreadã®æãå€æããŸããã 誰ãããã®ãã¹ãŠãæ°ã«ãããã©ã®ãããªçæã«è¡ã£ãã®ããç«ããé¡ãããŸãã
èšç»äž
COMããŒããä»ããŠéä¿¡ããç¹å®ã®ããã€ã¹ããããŸãã ããã«ãã¿ã¹ã¯ãå°ãè€éã«ããŸããããŒããŒãããå ¥åãããã³ãã³ããala-consoleãã®å©ããåããŠãããã³ããã€ã¹ãžã®ãªã¯ãšã¹ããã¿ã€ããŒã§éä¿¡ãããèªåã¢ãŒãã®äž¡æ¹ã§éä¿¡ââãããã§ãã ãŸããããã€ã¹ããã®å¿çãåãå ¥ããŠåŠçãããã©ãŒã ã«è¡šç€ºããå¿ èŠããããŸãã COMããŒããžã®ã¡ãã»ãŒãžã®éåä¿¡ã«é¢ãããã¹ãŠã®äœæ¥ã¯ãåå¥ã®ã¹ã¬ããã§å®è¡ããå¿ èŠããããŸãã ããã«ãããã°ã©ã ã®ããŸããŸãªå Žæããã³ã³ãã¥ãŒã¿ãŒã«æ¥ç¶ãããããã€ã¹ã«ã¡ãã»ãŒãžãéä¿¡ã§ããå¿ èŠããããŸãã ãŸãããã¹ãïŒhi TDDïŒãäœæã§ããããšãæãŸããã§ãã
Qt + MVPãã³ãã«é¢ããHabréã®èšäºã¯ãã§ã«ãããŸãã[1] ã Qtã§ã¹ã¬ããã䜿çšããããšã«é¢ããããã€ãã®èšäºããããŸã[2] ã [3] ã ã€ãŸããMVPã®æ¬è³ªã¯ãã¢ããªã±ãŒã·ã§ã³ããžãã¯ããã®å€èŠ³ããåé¢ãããŠããããšã§ããããã«ããããŠããããã¹ãã䜿çšããŠãã®ããžãã¯ãããã°ã©ã ã®æ®ãã®éšåããåå¥ã«ãã¹ãããä»ã®ã¢ããªã±ãŒã·ã§ã³ã§äœ¿çšããå€åããèŠä»¶ãæºããããã«å€æŽãè¿ éã«è¡ãããšãã§ããŸãã
çšèªã«ã€ããŠå°ãïŒ
衚瀺 -ããã°ã©ã ã®è¡šç€ºãæ åœããŸããããããã©ãŒã ã«ãªããŸãã
ã¢ãã« -ããã°ã©ã ã®ããžãã¯ãæ åœããããããã¡ãã»ãŒãžãCOMããŒãã«éä¿¡ãããçä¿¡å¿çãã±ããããã®äžã§åæãããŸãã
ãã¬ãŒã³ã¿ãŒã¯ããã¥ãŒãšã¢ãã«ã®éã®ãªã³ã¯ã§ãã
ããã«ã€ããŠç°¡åã«èª¬æãããšã ãã¡ããšãã¡ãã§è©³ããèªãããšãã§ããŸã ã ã³ãŒãã«åãæããæã§ãã
å°ããªã¢ããªã±ãŒã·ã§ã³ïŒæåŸã«å®æãããããžã§ã¯ããžã®ãªã³ã¯ïŒãäœæããäœææã«èšäºã®ã¿ã€ãã«ã«é 眮ãããŠãããã®ãå®è£ ããŸãã
ã¢ãã«
ç§ã¯ãã€ã³ã¿ãŒãã§ã€ã¹ã§ã¯ãªãããžãã¯ã§ããã°ã©ã ãæžãå§ããã®ã奜ãã§ãã
ãã®ãããModelComPortã¯ã©ã¹ãèšè¿°ããããšããäœæ¥ãéå§ããŸãã
æåã«ãCOMããŒããžã®ã¡ãã»ãŒãžéä¿¡ãå®è£ ããŸãã
ç§ãã¡ã®ã¯ã©ã¹ã¯ïŒ
- ã·ã¹ãã ã§äœ¿çšå¯èœãªCOMããŒããèªåçã«æ€åºããŸãã
- æå®ããé床ã§ãæå®ããCOMããŒããšã®æ¥ç¶ã確ç«ããŸãã
- COMããŒãã«ã¡ãã»ãŒãžãéä¿¡ããŸãã
- COMããŒãããåä¿¡ããã¡ãã»ãŒãžã解èªããŸãã
衚瀺ã¯æ¬¡ã®ãšããã§ãã
ModelComPort.h
class ModelComPort { public: ModelComPort(); ~ModelComPort(); // COM- void connectToComPort(); // void setPortName(QString portName); QString getPortName() const; // void setBaudrate(int baudrate); int getBaudrate() const; // COM- QList<QString> getListNamePorts() const; // bool isConnect() const; // COM- void onCommand(QString command); // COM- void response(QByteArray msg); private: // COM- void searchComPorts(); // void sendCommand(int command); private: bool m_connected; // COM- QString m_portName; // COM- QList<QString> m_listPorts; // COM- // int m_baudrate; int m_dataBits; int m_parity; int m_stopBits; int m_flowControl; QByteArray m_inBuf; // ComPortThread thread; // };
ã芧ã®ãšãããå€æŽãããå¯èœæ§ã®ããããããã£ã«ã€ããŠã¯ãgetã¡ãœãããšsetã¡ãœãããèšå®ããŸãã çŸæç¹ã§ã¯ãComPortThreadãªã©ã®ãªããžã§ã¯ãã«æ³šæãæããªãã§ãã ããã以äžã§èª¬æããŸãã
ModelComPort.cppãã¡ã€ã«ã¯åŒçšããŸãããããã€ãã®ãã¥ã¢ã³ã¹ã®ã¿ã説æããŸãã
ã³ã³ã¹ãã©ã¯ã¿ãŒ
ModelComPort::ModelComPort() : m_portName(""), m_baudrate(QSerialPort::Baud9600), m_dataBits(QSerialPort::Data8), m_parity(QSerialPort::NoParity), m_stopBits(QSerialPort::OneStop), m_flowControl(QSerialPort::NoFlowControl), m_connected(false) { searchComPorts(); }
ã芧ã®ãšããããã¶ã€ããŒã§ãããã©ã«ãã®éä¿¡ãã©ã¡ãŒã¿ãŒãããã«æ§æããã·ã¹ãã ã«ã€ã³ã¹ããŒã«ãããŠããCOMããŒããå€å¥ããŸãã é åã«å ¥ãããã¹ãŠã®å©çšå¯èœãªCOMããŒãã®ååã ãããè¡ãããçç±ã説æãããŠãã ããã äºå®ãå°æ¥æ¥ç¶ãã©ã¡ãŒã¿ã衚瀺ãããã©ãŒã ã¯ãã·ã¹ãã ã§äœ¿çšå¯èœãªCOMããŒãã«ã€ããŠäœãç¥ããããã®èœåã¯ãããŸããã ãã ãããŠãŒã¶ãŒã«æ¥ç¶ããç¹å®ã®COMããŒããéžæããå¿ èŠããããããä»åŸãã®ãªã¹ãããã©ãŒã ã«è»¢éããŸãã
å©çšå¯èœãªCOMããŒãã決å®ããæ¹æ³ã¯éåžžã«ç°¡åã§ãã
void ModelComPort::searchComPorts() { foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { m_listPorts.append(info.portName()); } }
次ã«ãæ¥ç¶ãäœæããæ¹æ³ãæ€èšããŸãã
connectToComPort
void ModelComPort::connectToComPort() { if (!m_connected) { if (m_portName == "") { return; } if (!thread->isRunning()) { thread.connectCom(m_portName, m_baudrate, m_dataBits, m_dataBits, m_stopBits, m_flowControl); thread.wait(500); // if (thread.isConnect()) { m_connected = true; } } } else { if (thread.isConnect()) { thread.disconnectCom(); } m_connected = false; } }
ããã§ã¯ãã¹ãŠãç°¡åã§ãã ãŸãããã§ã«æ¥ç¶ãããŠãããã©ãããå€æããŸãã ããã¯ãåããã¿ã³ãã¯ãªãã¯ãããšããŠãŒã¶ãŒãããŒãã«æ¥ç¶ããããŒãããåæã§ããããã«ããããã§ãã ã€ãŸããããšãã°ãããŒãæã«ç¡å¹ã«ãªããŸãã æ¥ç¶ãã¿ã³ã1åæŒããšæ¥ç¶ãããæ¥ç¶ãã¿ã³ã2åæŒããšåæãããŸãã ãããŠåã§ã
次ã«ãæ¥ç¶å ã®COMããŒãã®ååãç¥ã£ãŠãããã©ãããå€æããŸãã 次ã«ãããŒãã§åäœããã¹ã¬ãããéå§ãããã©ããã確èªããŸãã ã¹ã¬ãããå®è¡ãããŠããªãå Žåã¯ãäœæããŠéå§ãããã§ã«COMããŒãã«æ¥ç¶ãããŠããŸãã ããã§ãããããã詳现ã«åæ¢ãã䟡å€ããããŸãã å®éã«ã¯ãå¥ã®ã¹ã¬ããã§COMããŒããæäœããã«ã¯ããã®åãã¹ã¬ãããæäœäžã«æ¥ç¶ãäœæããå¿ èŠããããŸãã ãããã£ãŠãModelComPortã¯ã©ã¹ã§ã¯ãèªåã§æ¥ç¶ãäœæããã®ã§ã¯ãªããæ¥ç¶ãäœæããæ¥ç¶ãããã©ã¡ãŒã¿ãŒãæž¡ãããšãã¹ããªãŒã ã«äŒããŸãã
次ã«ãã¹ã¬ããã«æ¥ç¶ãäœæããæéãäžããæ¥ç¶ãäœæã§ãããã©ããã確èªããŸãã ãã¹ãŠé 調ã§ããã°ãæ¥ç¶ãããŠãããšãããã©ã°ãèšå®ããŸãã
æåŸã«ãçŸåšã®æ¥ç¶èšå®ã確ç«ãŸãã¯ååŸã§ããã¡ãœãããšãçŸåšã®æ¥ç¶ç¶æ ãååŸã§ããã¡ãœããããããŸãã
ã³ãŒãã¯éåžžã«ç°¡åã§ãã
void ModelComPort::setPortName(QString portName) { m_portName = portName; } QString ModelComPort::getPortName() const { return m_portName; } void ModelComPort::setBaudrate(int baudrate) { m_baudrate = baudrate; } int ModelComPort::getBaudrate() const { return m_baudrate; } bool ModelComPort::isConnect() const { return m_connected; }
æ¡ä»¶ã®1ã€ã¯ã¿ã€ããŒãšã³ã³ãœãŒã«ã®äž¡æ¹ããã³ãã³ããèªåçã«éä¿¡ã§ããããšã§ãã£ããããã³ã³ãœãŒã«ããããã¹ãã³ãã³ããåä¿¡ããããã解èªããŠCOMããŒãã«éä¿¡ããã¡ãœãããå¿ èŠã§ãã
å ¥åã¡ãœããã¯ãã³ã³ãœãŒã«ããè¡ãåãåãã察å¿ããã³ãã³ããéä¿¡ããŸãã
void ModelComPort::onCommand(QString command) { if (command == "On") { sendommand(ON); } else if (command == "Off") { sendommand(OFF); } .... }
ç§ãã¡ãæã£ãŠãããã¹ãŠã®ã³ãã³ãã¯ãå¥ã®ãã¡ã€ã«ã«é 眮ããã3æ¡ã®ã³ãŒããæã¡ãŸãã
Enum Commands { ON = 101, OFF = 102 .... }
ããŠãsendommandã¡ãœããã¯ãã±ããã圢æããéä¿¡ã®ããã«ã¹ã¬ããã«æž¡ããŸãïŒ
sendCommand
void ModelComPort::sendCommand(int command) { QByteArray buffer; quint8 checkSumm = 0; buffer[0] = '#'; buffer[1] = '<'; buffer[2] = 0; checkSumm ^= buffer[2]; buffer[3] = command; checkSumm ^= buffer[3]; buffer[4] = checkSumm; thread.transaction(buffer, 250); }
æååthread.transactionã®æ°å€250ïŒãããã¡ã250ïŒã ããã¯ãããã±ãŒãžãéä¿¡ããããªç§åäœã®æéã§ãã ãã®æéäžã«ãã±ãããéä¿¡ã§ããªãã£ãå Žåãããã€ã¹ãšã®éä¿¡ããªããšèŠãªãããšã©ãŒã衚瀺ããŸãã
ModelComPortã¯ã©ã¹ã«ã¯ãã¹ãŠã®ãã®ããããŸããã次ã«PresenterComPortã¯ã©ã¹ã®äœæã«é²ã¿ãŸãã
çºè¡šè
åè¿°ã®ããã«ãPresenterã¯ViewãšModelã®äžéã§ãã ã€ãŸããäºéã®æ©èœããããŸãã äžæ¹ã§ã¯ããã®ã¯ã©ã¹ã¯GUIã§å®è¡ããããã¹ãŠã®ãŠãŒã¶ãŒã¢ã¯ã·ã§ã³ã«å¿çããå¿ èŠããããŸãã äžæ¹ããã¹ãŠã®ãã¥ãŒãšã¢ãã«ã®åæãæäŸããå¿ èŠããããŸãã ã€ãŸããè€æ°ã®ãã¥ãŒãããå Žåããããã«è¡šç€ºãããäžè¬æ å ±ã¯åãã§ããå¿ èŠããããŸãã ããã¯ã第äžã«ã第äºã«ãïŒç§ãã¡ã®ïŒãã¥ãŒã«å ¥åãããããŒã¿ã¯ãã¢ãã«ãåäœããããŒã¿ãšåæããå¿ èŠããããšããããšã§ãã
ãã¬ãŒã³ã¿ãŒãã芧ãã ããã
PresenterComPort
class PresenterComPort : public QObject { Q_OBJECT public: explicit PresenterComPort(QObject *parent = 0); ~PresenterComPort(); void appendView(IViewComPort *view); private slots: // Com- void processConnect(); // Com- void processNameComPortChanged(QString portName); // Com- void processBaudratePortChanged(int baudrate); // COM- void onCommand(QString command); // COM- void response(const QByteArray& msg); private: void refreshView() const; void refreshView(IViewComPort *view) const; void setPortInfo() const; void setPortInfo(IViewComPort *view) const; private: ModelComPort *m_model; QList<IViewComPort*> m_viewList; ComPortThread thread; };
ã芧ã®ãšããããããªãã¯ã¡ãœããã¯1ã€ãããããŸãããããã¯ãïŒç§ãã¡ã®ïŒãã¥ãŒãPresenterã«ãã€ã³ãããããã«äœ¿çšãããŸãã ãã¥ãŒãåäžã®ãªããžã§ã¯ããšããŠæäœããã«ã¯ããã¹ãŠã®ãã¥ãŒã1ã€ã®ã€ã³ã¿ãŒãã§ã€ã¹ããç¶æ¿ããå¿ èŠããããŸãã ãã®å Žåã1ã€ã®ãã¥ãŒã䜿çšãããããIViewComPortã€ã³ã¿ãŒãã§ã€ã¹ããç¶æ¿ããŸãã ãã®å®è£ ã®è©³çŽ°ã«ã€ããŠã¯ããã¡ã[1]ãã芧ãã ãã ã appendViewïŒïŒã¡ãœããããã詳现ã«æ€èšããŠãã ããã
appendView
void PresenterComPort::appendView(IViewComPort *view) { // if (m_viewList.contains(view)) { return; } m_viewList.append(view); QObject *view_obj = dynamic_cast<QObject*>(view); // COM- QObject::connect(view_obj, SIGNAL(processConnect()), this, SLOT(processConnect())); // COM- QObject::connect(view_obj, SIGNAL(processNameComPortChanged(QString)), this, SLOT(processNameComPortChanged(QString))); // QObject::connect(view_obj, SIGNAL(processBaudratePortChanged(int)), this, SLOT(processBaudratePortChanged(int))); // COM- QObject::connect(view_obj, SIGNAL(onCommand(QString)), this, SLOT(onCommand(QString))); refreshView(view); setPortInfo(view); }
ãã®äžã«ãéä¿¡ããããã¥ãŒããªã¹ãããããã¬ãŒã³ã¿ãŒã¯ãã®ãã¥ãŒããæ¥ãä¿¡å·ã«æ¥ç¶ãããŸãã ããã¯ããã©ãŒã äžã®ãã¹ãŠã®å€æŽã«ã€ããŠãã¬ãŒã³ã¿ãŒã«ç¥ãããããã ãã«è¡ãããŸãã
ãã¹ãŠã®ã¡ãœããã«ã€ããŠã¯èª¬æããŸãããã³ãŒãã¯ããã§è€éã§ã¯ãããŸãããæ¥ç¶ãã©ã¡ãŒã¿ãŒãïŒç§ãã¡ã®ïŒãã¥ãŒã«èšå®ãã1ã€ã®ã¡ãœããã®äŸã«çŠç¹ãåœãŠãŸãã äžèšã§è¿°ã¹ãããã«ããã©ãŒã ã¯ã·ã¹ãã å ã®COMããŒããèªèããŸãããããŠãŒã¶ãŒã¯æ¥ç¶ããåã«ãã®æ å ±ã衚瀺ããå¿ èŠããããŸãã ãã®ãã¹ãŠãã¡ãœãããäœããŸã
setPortInfo
void PresenterComPort::setPortInfo(IViewComPort *view) const { // COM- QList<QString> tempList = m_model->getListNamePorts(); // COM- for (int i = 0; i < tempList.count(); i++) { view->addPortName(tempList.at(i)); } // view->addBaudrate(9600); view->addBaudrate(34800); view->addBaudrate(115200); }
ã芧ã®ãšãããã¢ãã«ãããã¹ãŠã®COMããŒãã®ãªã¹ããèŠæ±ãããã®æ å ±ããã©ãŒã ã«å ¥åããŸãã
ç§ã¯å¯èœãªæ¥ç¶é床ãå³å¯ã«ä¿®æ£ããŸãã;ç§ã®ä»äºã§ã¯ã»ãšãã©ã®å Žå9600ã䜿çšããŸããã念ã®ããããã«ããã€ãè¿œå ããŸããã
æ®ãã®ã³ãŒãã¯ãèšäºã®æåŸã«ã¬ã€ã¢ãŠããããŠãããããžã§ã¯ãã§èŠãããšãã§ããŸããããã以å€ã®å Žåã¯ããã§ã«éåžžã«æ¡åŒµãããŠãããããã«å€ãã®ããšãè°è«ãããŠããŸãã
衚瀺ãã
ãã©ãŒã ã«ã¯ãæ¥ç¶èšå®ãèšå®ããããã®2ã€ã®ã³ã³ãããã¯ã¹ãšãCOMããŒããžã®æ¥ç¶/åæãæ åœãã1ã€ã®ãã¿ã³ããããŸãã ãŸããã³ãã³ããæžã蟌ãã³ã³ãœãŒã«ãçšæãããŸãã ãŸããæ¥ç¶ã®çŸåšã®ã¹ããŒã¿ã¹ã衚瀺ããLEDããããŸãã æ¥ç¶ãããŠããå Žåãç·è²ã«ç¹ç¯ããŸãã
æçµçãªãã©ãŒã ãã¥ãŒã以äžã«ç€ºããŸãã
ãã©ãŒã ã³ãŒãèªäœã¯ç¹ã«éèŠã§ã¯ãããŸãããåComboBoxã§éžæãããé ç®ãå€æŽããããšãã«ä¿¡å·ãéä¿¡ããæ¥ç¶ãã¿ã³ãæŒããããšãã«ä¿¡å·ãéä¿¡ããŸãã
ãããã®ä¿¡å·ã¯ãã¹ãŠãã¬ãŒã³ã¿ãŒã«ãã£ãŠã€ã³ã¿ãŒã»ãããããããã«åŠçããããã«ããŒã¿ãã¢ãã«ã«éä¿¡ããŸãã
ã¹ã¬ããã®å®è£ ã«ç§»ããŸããããã¹ã¬ããã®å®è£ ã¯ãCOMããŒãã®æäœãæ åœããŸãã
Qtã®ã¹ã¬ããã§ã®äœæ¥ãããè¯ãæŽçããæ¹æ³ã«ã€ããŠã¯ãããã€ãã®æèŠããããŸãã 誰ããã¹ã¬ãããäœæããŠããã«ããŒã¿ãå ¥ãã誰ããQthreadããç¶æ¿ããŠrunïŒïŒã¡ãœãããåå®çŸ©ããŸãã ããããã®æ¹æ³ã«ã¯é·æãšçæããããŸãã ãã®å Žåã2çªç®ã®æ¹æ³ã«é²ã¿ãQthreadããç¶æ¿ããŸãã
ComPortThread
ããã§ã¯ãComPortThreadã¯ã©ã¹ãèŠãŠã¿ãŸãããã
ComPortThread.h
class ComPortThread : public QThread { Q_OBJECT public: ComPortThread(QObject *parent = 0); ~ComPortThread(); // COM- void transaction(const QByteArray& request, int waitTimeout); // COM- void connectCom(QString namePort, int baudRate, int m_dataBits, int m_parity, int m_stopBits, int m_flowControl); // COM- void disconnectCom(); // bool isConnect(); signals: // void responseMsg(const QByteArray &s); // COM- void error(const QString &s); // void timeout(const QString &s); protected: // void run(); private: int m_waitTimeout; // COM- QMutex mutex; QWaitCondition cond; // COM- QString m_portName; int m_baudrate; int m_dataBits; int m_parity; int m_stopBits; int m_flowControl; // COM- QByteArray m_request; // bool m_isConnect; // bool m_isDisconnecting; // bool m_isConnecting; // bool m_isQuit; // };
ã芧ã®ããã«ãã¢ãã«ããCOMããŒããžã®æ¥ç¶èšå®ãã¢ãã«ããéä¿¡ãããCOMããŒãã®çŸåšã®ç¶æ ïŒæ¥ç¶ãããŠãããã©ããïŒãããã³ã¹ããŒãžïŒæ¥ç¶/åæïŒããããŸãã
å®è£ ã«ç§»ããŸãã
ã³ã³ã¹ãã©ã¯ã¿ãŒ
ComPortThread::ComPortThread(QObject *parent) : QThread(parent), m_waitTimeout(0), m_isQuit(false), m_isConnect(false), m_isDisconnecting(false), m_isConnecting(false) { }
ããã§ã¯ãåæã¹ã¬ããã䜿çšããããšã®ãã人ããåæã¹ã¬ããã«æ £ããŠããªã人ã«ãšã£ãŠã¯æ°ããããšã¯ãªããšæããŸããQtã®ããã¥ã¡ã³ããåç §ããããšããå§ãããŸãã
æ¥ç¶æ¹æ³ã«ç§»åããŸãã
connectCom
void ComPortThread::connectCom(QString namePort, int baudRate, int dataBits, int parity, int stopBits, int flowControl) { mutex.lock(); m_portName = namePort; m_baudrate = baudRate; m_dataBits = dataBits; m_parity = parity; m_stopBits = stopBits; m_flowControl = flowControl; mutex.unlock(); // - if (!isRunning()) { m_isConnecting = true; start(); m_isQuit = false; } else { // , cond.wakeOne(); } }
ã芧ã®ãšãããããã§ã¯æ¥ç¶ãäœæããã®ã§ã¯ãªããã¯ãŒã¯ãããŒããããã©ããã確èªãããªãå Žåã¯æ°ããã¹ã¬ãããäœæããæ¥ç¶ãäœæããã€ã³ãã³ããã©ã°ãèšå®ããŸããåæãããæå³ãæããã«ããŸãã ã¹ã¬ããã«ãã£ãŠè¡ããããã¹ãŠã®äœæ¥ã¯runïŒïŒã¡ãœããã§è¡ããããªãŒããŒã©ã€ããããŸãã
disconnectCom
void ComPortThread::disconnectCom() { mutex.lock(); m_isDisconnecting = true; mutex.unlock(); cond.wakeOne(); }
ãããŒå€æ°ãå€æŽããåã«ãã¹ããªãŒã ããããã¯ããŠãããããã¯ã解é€ããå¿ èŠãããããšã«æ³šæããŠãã ããã å€æŽãããã«æå¹ã«ãããå Žåã¯ã圌ãèµ·ãããŠãã ããã
ãã¹ãŠã®æçšãªäœæ¥ãå®è¡ãããã¡ã€ã³ã¡ãœããã«æ»ããŸãã
èµ°ã
void ComPortThread::run() { QSerialPort serial; // COM- QString currentPortName = m_portName; // int currentWaitTimeout = m_waitTimeout; // , COM- QByteArray currentRequest = m_request; while (!m_isQuit) { // COM- if (m_isConnecting) { // COM- serial.setPortName(currentPortName); // COM- if (serial.open(QIODevice::ReadWrite)) { // if ((serial.setBaudRate(m_baudrate) && serial.setDataBits((QSerialPort::DataBits)m_dataBits) && serial.setParity((QSerialPort::Parity)m_parity) && serial.setStopBits((QSerialPort::StopBits)m_stopBits) && serial.setFlowControl((QSerialPort::FlowControl)m_flowControl))) { m_isConnect = true; m_isConnecting = false; } else { m_isConnect = false; m_isConnecting = false; emit error(tr("Can't open %1, error code %2") .arg(m_portName) .arg(serial.error())); return; } } else { m_isConnect = false; m_isConnecting = false; emit error(tr("Can't open %1, error code %2") .arg(m_portName) .arg(serial.error())); return; } } else if (m_isDisconnecting) { serial.close(); m_isDisconnecting = false; m_request.clear(); m_isQuit = true; } else { // COM- if (!currentRequest.isEmpty()) { serial.write(currentRequest); // if (serial.waitForBytesWritten(m_waitTimeout)) { // if (serial.waitForReadyRead(currentWaitTimeout)) { // QByteArray responseFromPort = serial.readAll(); while (serial.waitForReadyRead(10)) { responseFromPort += serial.readAll(); } // , emit responseMsg(responseFromPort); } else { // emit timeout(tr("Wait read response timeout %1") .arg(QTime::currentTime().toString())); } } else { // emit timeout(tr("Wait write request timeout %1") .arg(QTime::currentTime().toString())); } // currentRequest.clear(); } else { mutex.lock(); // cond.wait(&mutex); currentWaitTimeout = m_waitTimeout; currentRequest = m_request; mutex.unlock(); } } } }
ãŸããããŒã«ã«å€æ°ãäœæããŸããããŒã«ã«å€æ°ã«ã¯ããããŒäžã«å€åããå¯èœæ§ã®ããæ å ±ãå ¥åããŸãã 次ã«ãçµäºããããã©ã°ãèšå®ãããŸã§ã¹ããªãŒã ãå転ããç¡éã®ãµã€ã¯ã«ã«å ¥ããŸãã
ã¹ããªãŒã ãå転ãããªããããã©ã°ã確èªãããã©ã°ã«åŸã£ãŠç¹å®ã®ã¢ã¯ã·ã§ã³ãå®è¡ããŸãã äžçš®ã®ã¹ããŒããã·ã³ã ã€ãŸããCOMããŒãã«æ¥ç¶ããããšã瀺ããã©ã°ãããå Žåã¯ãæ¥ç¶ããŠãã®ãã©ã°ããªã»ããããå¥ã®ã³ãã³ããçºè¡ããããŸã§ã¹ãªãŒãç¶æ ã«ãªããŸãã ããã«ãCOMããŒãã«ã¡ãã»ãŒãžãéä¿¡ããã³ãã³ããå°çãããšãã¹ã¬ãããèµ·åããéä¿¡ããå¿ èŠã®ããã¡ãã»ãŒãžãåãåããæå®ãããæéå ã«éä¿¡ãè©Šã¿ãŸãã éä¿¡ã§ããªãã£ãå Žåãã¹ããªãŒã ã¯å€éšãªããžã§ã¯ãããµãã¹ã¯ã©ã€ãã§ããä¿¡å·ãéä¿¡ããéä¿¡ã倱æããããšã確èªããŸãã
éä¿¡ãæåããå Žåãã¹ããªãŒã ã¯æå®ãããæéã ãå¿çãåŸ æ©ããŸãã çããåŸãããªãå Žåãã¹ããªãŒã ã¯ä¿¡å·ãéä¿¡ããŸãããããããã¹ãŠã®ãªããžã§ã¯ãããµãã¹ã¯ã©ã€ãã§ãããããéçãå¿çããŠããªãããšããããããã§ã«å¯ŸåŠããŠããŸãã
åçãåä¿¡ããããšãã¹ããªãŒã ã¯åã³ããŒã¿ã®æºåãã§ããŠãããšããä¿¡å·ãçºããããããååŸããŠåŠçããããšãã§ããŸãã
ããã
äžè¬çã«ãèšèã§ã¯ç°¡åã«èãããŸããããã¥ã¢ã³ã¹ããããŸãã å®éãã¢ãã«ã¯ä¿¡å·ãåä¿¡ã§ããŸããã ã€ãŸããããã±ãŒãžãå±ããŸããããModelã¯ãããç¥ããŸããã äžæ¹ãPresenterã¯ä¿¡å·ãåä¿¡ã§ããŸãïŒQobjectããç¶æ¿ãããŠããããïŒããPresenterã¯COMããŒãã§åäœããã¹ããªãŒã ã«ã¢ã¯ã»ã¹ã§ããŸããã 2ã€ã®è§£æ±ºçããããŸãïŒãããããã³ã¡ã³ããæžããŠç¥ã£ãŠãã人ãããŸãïŒãæåã®ãªãã·ã§ã³ã¯Presenterã§ã¹ããªãŒã ãæäœããããšã§ãã ããŸãè¯ãã¢ã€ãã¢ã§ã¯ãªãããã«æããŸããããã®ãããPresenterãžã®ã¡ãã»ãŒãžã®ããã¯/ã¢ã³ããã¯ã®äœæ¥ãè¡ãå¿ èŠããããŸããã€ãŸããããã°ã©ã ããžãã¯ã®äžéšã¯ã¢ãã«ã§ã¯ãªãPresenterã«ãããŸãã ç§ã¯ãã®èããæšãŠãŸããã 2çªç®ã®ãªãã·ã§ã³ã¯ãã¯ã©ã¹ComPortThread Singletonãäœæããããšã§ãã ãããŠãPresenterãã·ã°ãã«ã«ãµãã¹ã¯ã©ã€ãããModelã§ãã¹ãŠã®åŠçãå®è¡ããŸããããè¡ãã«ã¯ãComPortThreadã¯ã©ã¹ãå°ãããçŽãå¿ èŠããããŸãã
ComPortThread
class ComPortThread : public QThread { Q_OBJECT public: static ComPortThread* getInstance() { static QMutex mutex; if (!m_instance) { mutex.lock(); if (!m_instance) { m_instance = new ComPortThread; } m_refCount++; mutex.unlock(); } return m_instance; } void run(); void transaction(const QByteArray& request, int waitTimeout); void connectCom(QString namePort, int baudRate, int m_dataBits, int m_parity, int m_stopBits, int m_flowControl); void disconnectCom(); bool isConnect(); void free(); signals: void responseMsg(const QByteArray &s); void error(const QString &s); void timeout(const QString &s); private: ComPortThread(QObject *parent = 0); ~ComPortThread(); ComPortThread(const ComPortThread&); ComPortThread& operator=(const ComPortThread&); private: int m_waitTimeout; QMutex mutex; QWaitCondition cond; QString m_portName; int m_baudrate; int m_dataBits; int m_parity; int m_stopBits; int m_flowControl; QByteArray m_request; bool m_isConnect; bool m_isDisconnecting; bool m_isConnecting; bool m_isQuit; static ComPortThread* m_instance; static int m_refCount; };
ãã¶ã€ããŒãšãã¹ãã©ã¯ã¿ãå€éšã¢ã¯ã»ã¹ããé ãããªã³ã¯ãååŸããã¡ãœãããå®è£ ããModelComPortã¯ã©ã¹ãšPresenterComPortã¯ã©ã¹ã§ã³ã³ã¹ãã©ã¯ã¿ã«è¡ãè¿œå ããŸãã
thread = ComPortThread::getInstance();
ãããã®ã¯ã©ã¹ã®ãã¹ãã©ã¯ã¿ã«è¡ãè¿œå ããããšãå¿ããªãã§ãã ããïŒ
if (thread) { thread->free(); thread = 0; }
ã¹ã¬ãããªããžã§ã¯ãã®freeïŒïŒã¡ãœããã¯ããèªäœãžã®åç §ãã«ãŠã³ããããŒãã«ãªããšããã«åé€ãèš±å¯ããŸãã ããã¯ããã³ã°ãªã³ã°ãªã³ã¯ãå¯èœãªãªããžã§ã¯ãã®åé€ãé²ãããã«è¡ãããŸãã ãããã£ãŠãComPortThreadãªããžã§ã¯ãã䜿çšãããã¹ãŠã®ã¯ã©ã¹ã§ããªããžã§ã¯ãã®å®£èšããã€ã³ã¿ãŒã®å®£èšã«å€æŽãããã€ã³ã¿ãŒãä»ããŠã¹ããªãŒã ãæäœããŸãã 詳现ã¯ãœãŒã¹ã«ãããŸãã
æåŸã«ããã¹ãŠããŸãšããŠãmain.cppãã¡ã€ã«ãäœæããŸã
main.cpp
int main(int argc, char *argv[]) { QApplication a(argc, argv); CopterGUI w = new CopterGUI; PresenterComPort *presenterComPort = new PresenterComPort(); presenterComPort->appendView(&w); w.show(); return a.exec(); }
ãããã«
ãŸããããããã¹ãŠã§ãã
ããªãã®ãã£ãŒãããã¯ãææ¡ãæ¹å€ã¯èå³æ·±ãã§ãã
ããªã¥ãŒã ãéåžžã«å€§ããããšãå€æãããããã§ããã ãå€ãã®å®è£ ã®è©³çŽ°ã匷調ãããã®ã§ã質åãããã°ã³ã¡ã³ãã§çããããšããŸãã PMã®ãšã©ãŒã«ã€ããŠæžããŠãã ããã
ç§ããã¯ããã®å®è£ ã¯çµ¶å¯Ÿã«æ£ãããšäž»åŒµããã®ã§ã¯ãªãããããäœæããæ¹æ³ã«é¢ãããªãã·ã§ã³ã®1ã€ã®èª¬æã§ãã ãã®èšäºã¯ç§ã«ãšã£ãŠæåã®ãã®ã§ãã®ã§ãããŸã蹎ããªãã§ãã ããã çŽæããããããžã§ã¯ãã³ãŒãã¯ã ããã§ååŸã§ããŸã ã
PSã³ã¡ã³ãã§å°æ¬ãããŠããkulinichãšsemlanikã«ãã£ãŠäžããããã³ãŒãã«é¢ããå°ããªã³ã¡ã³ããä¿®æ£ããŸããã
PPSãã£ã¹ã«ãã·ã§ã³ã®æäžã«ãå°æ¬ãããSingerofthefallã«ãã£ãŠæäŸãããããŒã1ãšããŒã2ã®ãªã³ã¯ã®ãããã§ãèšäºã§èª¬æãããŠããã¹ããªãŒã ãæäœããã¢ãããŒãã¯ãåžžã«ããã°ã©ããŒã®æåŸ ã«å¿ããããšãã§ãããæå³ãããšããã«åäœããªãããšãå€æããŸããã
æåã®ã³ã¡ã³ãã§æšå¥šãããŠããããã«ãã¹ã¬ããã®æäœã«ã¯Qobject.moveToThreadïŒïŒã¡ãœããã䜿çšããæ¹ãå®å šã§ãã