1 // Copyright (c) 2012 Dennco Project
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 // Created by tkawata on Apr/15/2012.
19 #include "qtdnserialportimpl.h"
21 #include "ui_portinfodialog.h"
22 #include "DNServerSerialPort.h"
24 #include "mainwindow.h"
27 #include "DNSettings.h"
30 #include <QtCore/QVariant>
35 class SleeperThread : public QThread
38 static void msleep(unsigned long msecs)
40 QThread::msleep(msecs);
44 DNSerialPortImpl * DNSerialPortImpl::create(DNServerSerialPort *server)
46 return new QtDNSerialPortImpl(server);
50 QtDNSerialPortImpl::QtDNSerialPortImpl(DNServerSerialPort *server) :
51 DNSerialPortImpl(server), mSerialCommunicationThread(NULL), mHandlerThread(NULL), mStopping(false),
54 mBaudRate(SerialPort::Rate9600),
55 mDataBits(SerialPort::Data8),
56 mParity(SerialPort::NoParity),
57 mStopBits(SerialPort::OneStop),
58 mFlowControl(SerialPort::NoFlowControl)
62 QtDNSerialPortImpl::~QtDNSerialPortImpl()
65 if (mSerialCommunicationThread)
67 delete mSerialCommunicationThread;
68 mSerialCommunicationThread = NULL;
72 delete mHandlerThread;
73 mHandlerThread = NULL;
77 bool QtDNSerialPortImpl::setup()
79 if (!MainWindow::instance)
82 QtDNSerialPortSettingDialog dialog(MainWindow::instance);
87 mPortName = dialog.getSelectedPortName();
88 mBaudRate = (SerialPort::Rate) dialog.getSelectedRate();
89 mDataBits = dialog.getSelectedDataBits();
90 mParity = dialog.getSelectedParity();
91 mStopBits = dialog.getSelectedStopBits();
92 mFlowControl = dialog.getSelectedFlowControl();
100 bool QtDNSerialPortImpl::isRunning()
102 DNLocker lock(&mStartStopLock);
106 void QtDNSerialPortImpl::start()
109 mStartStopLock.lock();
113 mSerialCommunicationThread = DNThread::createThread(QtDNSerialPortImpl::serialCommunicationThreadBody, this);
114 mHandlerThread = DNThread::createThread(QtDNSerialPortImpl::requestHandelrThreadBody, this);
116 mSerialCommunicationThread->start();
117 mHandlerThread->start();
119 mStartStopLock.unlock();
122 void QtDNSerialPortImpl::stop()
124 mStartStopLock.lock();
128 if (mSerialCommunicationThread)
130 mSerialCommunicationThread->waitForExit(1000);
131 delete mSerialCommunicationThread;
132 mSerialCommunicationThread = NULL;
136 mHandlerThread->waitForExit(1000);
137 delete mHandlerThread;
138 mHandlerThread = NULL;
140 mRequestQueue.clear();
142 mStartStopLock.unlock();
145 void QtDNSerialPortImpl::sendMessage(const char* message)
147 mResponseStringLock.lock();
148 mResponseString.append(message);
149 mResponseStringLock.unlock();
150 mSerialWriteSemaphore.release(1);
154 void QtDNSerialPortImpl::serialCommunicationThreadBody(void *_impl)
159 QtDNSerialPortImpl *impl = (QtDNSerialPortImpl*)_impl;
161 if (impl->mPortName.length()==0 || impl->mBaudRate == 0)
163 impl->mStartStopLock.lock();
164 impl->mStopping = true;
165 impl->mStartStopLock.unlock();
169 SerialPort *port = NULL;
174 port = new SerialPort(impl->mPortName);
179 r = port->open(QIODevice::ReadWrite | QIODevice::Unbuffered);
183 if (!port->setRate(impl->mBaudRate))
190 if (!port->setDataBits(impl->mDataBits))
197 if (!port->setParity(impl->mParity))
204 if (!port->setStopBits(impl->mStopBits))
211 if (!port->setFlowControl(impl->mFlowControl))
219 SleeperThread::msleep(500);
227 TKLog::printf("Failed to open the serial port. retrying...");
229 } while (!r && retry >= 0);
237 impl->mStartStopLock.lock();
238 impl->mStopping = true;
239 impl->mStartStopLock.unlock();
240 TKLog::printf("Failed to open the serial port. giving up!");
248 while(!impl->mStopping)
250 if (port->bytesAvailable() > 0)
252 int len = port->read( (buffer + p), sizeof(buffer) - p);
258 if (buffer[i] == '\r' || buffer[i] == '\n' || i == sizeof(buffer)-1)
263 impl->mRequestQueueLock.lock();
264 impl->mRequestQueue.push_back(QString::fromLocal8Bit(buffer));
265 impl->mRequestQueueLock.unlock();
266 impl->mQueueSemaphore.release(1);
271 if (buffer[j]!='\r' && buffer[j]!='\n')
280 buffer[d] = buffer[j];
297 if (!impl->mSerialWriteSemaphore.tryAcquire(1,waitTime))
311 impl->mResponseStringLock.lock();
312 if (impl->mResponseString.length()>0 && port->isOpen())
314 QString response = impl->mResponseString;
315 impl->mResponseString.clear();
316 impl->mResponseStringLock.unlock();
317 port->write(response.toLocal8Bit());
321 impl->mResponseStringLock.unlock();
330 void QtDNSerialPortImpl::requestHandelrThreadBody(void *_impl)
335 QtDNSerialPortImpl *impl = (QtDNSerialPortImpl*)_impl;
336 while(!impl->mStopping)
338 impl->mQueueSemaphore.tryAcquire(1,100);
339 impl->mRequestQueueLock.lock();
340 if (!impl->mRequestQueue.isEmpty())
342 QString line = impl->mRequestQueue.dequeue();
343 impl->mRequestQueueLock.unlock();
347 QString seq = line.left(2);
348 QString cmd = line.mid(2,1);
349 QString par = line.mid(3);
353 TKLog::printf("(SERIALl):%s", par.toLocal8Bit().constData());
358 int idx = par.indexOf(",");
359 if (idx > 0 && par.length() > idx + 1)
361 QString path = par.left(idx);
362 float val = par.mid(idx+1).toFloat();
363 impl->mServer->getEngine()->doClientSetRequest(path.toLocal8Bit().constData(),val);
369 float val = impl->mServer->getEngine()->doClientGetRequest(par.toLocal8Bit().constData());
371 rep.append(QString::number(val));
373 impl->sendMessage(rep.toLocal8Bit().constData());
379 impl->mRequestQueueLock.unlock();
386 Q_DECLARE_METATYPE(SerialPortInfo)
388 QtDNSerialPortSettingDialog::QtDNSerialPortSettingDialog(QWidget *parent)
390 , ui(new Ui::QtDNSerialPortSettingDialog)
394 procUpdateAvailablePorts();
395 procItemPortChanged(0);
397 connect(ui->updateButton, SIGNAL(clicked()), this, SLOT(procUpdateAvailablePorts()));
398 connect(ui->portsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(procItemPortChanged(int)));
399 connect(ui->okPushButton, SIGNAL(clicked()), this, SLOT(procOKButtonClick()));
400 connect(ui->cancelPushButton, SIGNAL(clicked()), this, SLOT(procCancelButtonClick()));
403 QString defaultPortName = QString::fromStdString(DNSettings::getValue(DNSettings::SERIAL_PORTNAME , ""));
404 for (int i = 0; i < ui->portsComboBox->count(); i++)
406 if (ui->portsComboBox->itemText(i) == defaultPortName)
408 ui->portsComboBox->setCurrentIndex(i);
413 QString defaultBaudRate = QString::fromStdString(DNSettings::getValue(DNSettings::SERIAL_RATE, "9600"));
414 for (int i = 0; i < ui->ratesComboBox->count(); i++)
416 if (ui->ratesComboBox->itemText(i) == defaultBaudRate)
418 ui->ratesComboBox->setCurrentIndex(i);
423 QString defaultDataBits = QString::fromStdString(DNSettings::getValue(DNSettings::SERIAL_DATABITS, "8"));
424 for (int i = 0; i < ui->dataBitsComboBox->count(); i++)
426 if (ui->dataBitsComboBox->itemText(i) == defaultDataBits)
428 ui->dataBitsComboBox->setCurrentIndex(i);
433 QString defaultParity = QString::fromStdString(DNSettings::getValue(DNSettings::SERIAL_PARITY, "No parity"));
434 for (int i = 0; i < ui->parityComboBox->count(); i++)
436 if (ui->parityComboBox->itemText(i) == defaultParity)
438 ui->parityComboBox->setCurrentIndex(i);
443 QString defaultStopBits = QString::fromStdString(DNSettings::getValue(DNSettings::SERIAL_STOPBITS, "one stop"));
444 for (int i = 0; i < ui->stopBitsComboBox->count(); i++)
446 if (ui->stopBitsComboBox->itemText(i) == defaultStopBits)
448 ui->stopBitsComboBox->setCurrentIndex(i);
453 QString defaultFlowControl = QString::fromStdString(DNSettings::getValue(DNSettings::SERIAL_FLOWCONTROL, "No flow control"));
454 for (int i = 0; i < ui->flowControlComboBox->count(); i++)
456 if (ui->flowControlComboBox->itemText(i) == defaultFlowControl)
458 ui->flowControlComboBox->setCurrentIndex(i);
465 QtDNSerialPortSettingDialog::~QtDNSerialPortSettingDialog()
470 QString QtDNSerialPortSettingDialog::getSelectedPortName()
472 return ui->portsComboBox->currentText();
475 int QtDNSerialPortSettingDialog::getSelectedRate()
477 return ui->ratesComboBox->currentText().toInt();
480 SerialPort::DataBits QtDNSerialPortSettingDialog::getSelectedDataBits()
482 SerialPort::DataBits r = SerialPort::UnknownDataBits;
484 switch(ui->dataBitsComboBox->currentIndex())
487 r = SerialPort::Data5;
490 r = SerialPort::Data6;
493 r = SerialPort::Data7;
496 r = SerialPort::Data8;
503 SerialPort::Parity QtDNSerialPortSettingDialog::getSelectedParity()
505 SerialPort::Parity r = SerialPort::UnknownParity;
507 switch(ui->parityComboBox->currentIndex())
510 r = SerialPort::NoParity;
513 r = SerialPort::EvenParity;
516 r = SerialPort::OddParity;
519 r = SerialPort::SpaceParity;
522 r = SerialPort::MarkParity;
529 SerialPort::StopBits QtDNSerialPortSettingDialog::getSelectedStopBits()
531 SerialPort::StopBits r = SerialPort::UnknownStopBits;
533 switch(ui->stopBitsComboBox->currentIndex())
536 r = SerialPort::OneStop;
539 r = SerialPort::OneAndHalfStop;
542 r = SerialPort::TwoStop;
549 SerialPort::FlowControl QtDNSerialPortSettingDialog::getSelectedFlowControl()
551 SerialPort::FlowControl r = SerialPort::UnknownFlowControl;
553 switch(ui->flowControlComboBox->currentIndex())
556 r = SerialPort::NoFlowControl;
559 r = SerialPort::HardwareControl;
562 r = SerialPort::SoftwareControl;
570 void QtDNSerialPortSettingDialog::procUpdateAvailablePorts()
572 ui->portsComboBox->clear();
573 foreach (SerialPortInfo info, SerialPortInfo::availablePorts()) {
576 ui->portsComboBox->addItem(info.portName(), v);
579 ui->okPushButton->setEnabled(ui->portsComboBox->count() > 0);
582 void QtDNSerialPortSettingDialog::procItemPortChanged(int idx)
584 QVariant v = ui->portsComboBox->itemData(idx);
586 SerialPortInfo info = v.value<SerialPortInfo>();
588 ui->locationValueLabel->setText(info.systemLocation());
589 ui->descriptionValueLabel->setText(info.description());
590 ui->manufacturerValueLabel->setText(info.manufacturer());
594 void QtDNSerialPortSettingDialog::procOKButtonClick()
600 void QtDNSerialPortSettingDialog::procCancelButtonClick()
606 bool QtDNSerialPortSettingDialog::isOK()
609 DNSettings::setValue(DNSettings::SERIAL_PORTNAME, ui->portsComboBox->currentText().toStdString());
610 DNSettings::setValue(DNSettings::SERIAL_RATE, ui->ratesComboBox->currentText().toStdString());
611 DNSettings::setValue(DNSettings::SERIAL_DATABITS, ui->dataBitsComboBox->currentText().toStdString());
612 DNSettings::setValue(DNSettings::SERIAL_PARITY, ui->parityComboBox->currentText().toStdString());
613 DNSettings::setValue(DNSettings::SERIAL_STOPBITS, ui->stopBitsComboBox->currentText().toStdString());
614 DNSettings::setValue(DNSettings::SERIAL_FLOWCONTROL, ui->flowControlComboBox->currentText().toStdString());