qpidctrl  0.7.1
qpidcontroller.cpp
Go to the documentation of this file.
1 #include "qpidcontroller.h"
2 #include "qpiddevice.h"
3 #include "qpidsettings.h"
4 #include "qpiddevicethread.h"
5 #include "qpidobjectnamer.h"
6 #include <stdio.h>
7 #include "qcepdebug.h"
8 #include "qpidserverthread.h"
9 #include "qpidserver.h"
10 #include "qpidloggerthread.h"
11 #include "qpidlogger.h"
12 #include "qpidmainwindow.h"
13 #include "qextserialenumerator.h"
14 #include <math.h>
15 #include <limits>
16 #include <QDir>
17 #include "qpidserversession.h"
18 
20  QObject(parent),
21  m_ObjectNamer(this, "controller"),
22  m_MainWindow(NULL),
23  m_Saver(new QcepSettingsSaver(this)),
24  m_Debug(m_Saver, this, "debug", 0, "Debug Level"),
25  m_ControllerStatus(QcepSettingsSaverPtr(), this, "controllerStatus", Stopped, "Controller Status?"),
26  m_Connected(QcepSettingsSaverPtr(), this, "connected", false, "Device Connected?"),
27  m_DefaultDeviceNumber(m_Saver, this, "defaultDeviceNumber", 0, "Default Device Number"),
28  m_Temperature(QcepSettingsSaverPtr(), this, "temperature", nan(), "Temperature"),
29  m_RampPoint(QcepSettingsSaverPtr(), this, "rampPoint", nan(), "Ramp Point (current setpoint during ramp)"),
30  m_SetPoint (m_Saver, this, "setPoint", nan(), "Target Set Point"),
31  m_RampRate (m_Saver, this, "rampRate", 0, "Set Point Ramping Rate (or 0 for no ramping) in degC/min"),
32  m_HeatSetPoint(m_Saver, this, "heatSetPoint", 0, "Set Point for heating phase"),
33  m_HeatRampRate(m_Saver, this, "heatRampRate", 0, "Ramp rate for heating phase"),
34  m_SoakTime(m_Saver, this, "soakTime", 0, "Soak time"),
35  m_CoolRampRate(m_Saver, this, "coolRampRate", 0, "Ramp rate for cooling phase"),
36  m_Proportional (m_Saver, this, "proportional", 0, "Proportional term (%/degC)"),
37  m_Integral (m_Saver, this, "integral", 0, "Integral term"),
38  m_Derivative (m_Saver, this, "derivative", 0, "Derivative term"),
39  m_OutputLevel(QcepSettingsSaverPtr(), this, "outputLevel", nan(), "Output Level (%)"),
40  m_Enabled(m_Saver, this, "enabled", false, "Output Enabled?"),
41  m_LoopEnabled(m_Saver, this, "loopEnabled", false, "PID Loop Enabled?"),
42  m_ColumnNames(m_Saver, this, "columnNames", QStringList(), "Graph Column Names"),
43  m_SelectionCounter(m_Saver, this, "selectionCounter", 0, "Dummy Property used to force settings to be saved"),
44  m_GraphLength(m_Saver, this, "graphLength", 100, "Length of Temperature History"),
45  m_GraphInterval(m_Saver, this, "graphInterval", 5, "Update Interval for Temperature History in sec"),
46  m_WindowGeometry(m_Saver, this, "windowGeometry", QByteArray(), "Window Geometry Settings"),
47  m_WindowState(m_Saver, this, "windowState", QByteArray(), "Window State Settings"),
48  m_SettingsPath(QcepSettingsSaverPtr(), this, "settingsPath", "", "Settings saved in"),
50 {
51  connect(prop_DefaultDeviceNumber(), SIGNAL(valueChanged(int,int)), this, SLOT(onDefaultDeviceChanged(int)));
52 }
53 
55 {
56 }
57 
59 {
60  return std::numeric_limits<double>::quiet_NaN();
61 }
62 
63 void QPidController::printMessage(QString msg, QDateTime dt)
64 {
66 
67  if (win) {
68  win -> printMessage(msg, dt);
69  }
70 }
71 
73 {
75 
76  if (win) {
77  win -> criticalMessage(msg);
78  }
79 }
80 
82 {
83  m_MainWindow = window;
84 
86 
87  if (m_ServerThread) {
88  m_ServerThread -> start();
90  }
91 
93 
94  if (m_LoggerThread) {
95  m_LoggerThread -> start();
97  }
98 
100 
101  connect(prop_Debug(), SIGNAL(valueChanged(int,int)), this, SLOT(debugChanged(int)));
102 
103  readSettings();
104 
105  m_Saver->start();
106 
107  m_MainWindow->start();
108 }
109 
111 {
112 }
113 
114 QcepSettingsSaverPtr QPidController::saver()
115 {
116  return m_Saver;
117 }
118 
120 {
121  if (g_DebugLevel) {
122  g_DebugLevel->setDebugLevel(dbg);
123  }
124 }
125 
127 {
128  set_ControllerStatus(Starting);
129 
130  QPidDevicePtr dev = m_Devices[get_DefaultDeviceNumber()];
131 
132  connect(dev.data(), SIGNAL(loggedChannelNames(QStringList)), this, SLOT(onLoggedChannelNames(QStringList)));
133  connect(dev.data(), SIGNAL(loggedChannelValues(QcepDoubleList)), this, SLOT(onLoggedChannelValues(QcepDoubleList)));
134  connect(dev.data(), SIGNAL(graphedChannelNames(QStringList)), this, SLOT(onGraphedChannelNames(QStringList)));
135  connect(dev.data(), SIGNAL(graphedChannelValues(QcepDoubleList)), this, SLOT(onGraphedChannelValues(QcepDoubleList)));
136 
137  dev->set_RunState(true);
138 
139  set_ControllerStatus(Running);
140 }
141 
143 {
144  set_ControllerStatus(Stopping);
145 
146  QPidDevicePtr dev = m_Devices[get_DefaultDeviceNumber()];
147 
148  dev->set_RunState(false);
149 
150  disconnect(dev.data(), SIGNAL(loggedChannelNames(QStringList)), this, SLOT(onLoggedChannelNames(QStringList)));
151  disconnect(dev.data(), SIGNAL(loggedChannelValues(QcepDoubleList)), this, SLOT(onLoggedChannelValues(QcepDoubleList)));
152  disconnect(dev.data(), SIGNAL(graphedChannelNames(QStringList)), this, SLOT(onGraphedChannelNames(QStringList)));
153  disconnect(dev.data(), SIGNAL(graphedChannelValues(QcepDoubleList)), this, SLOT(onGraphedChannelValues(QcepDoubleList)));
154 
155  set_ControllerStatus(Stopped);
156 }
157 
159 {
160  set_ControllerStatus(Restarting);
161 
162  m_Devices[get_DefaultDeviceNumber()]->restart();
163 
164  set_ControllerStatus(Running);
165 }
166 
168 {
169  set_ControllerStatus(Paused);
170 }
171 
173 {
174  set_ControllerStatus(Running);
175 }
176 
178 {
179  QString res = "Unknown";
180 
181  switch(status) {
182  case Stopping:
183  res = "Stopping";
184  break;
185 
186  case Stopped:
187  res = "Stopped";
188  break;
189 
190  case Starting:
191  res = "Starting";
192  break;
193 
194  case Running:
195  res = "Running";
196  break;
197 
198  case Paused:
199  res = "Paused";
200  break;
201 
202  case Restarting:
203  res = "Restarting";
204  break;
205 
206  case Error:
207  res = "Error";
208  break;
209  }
210 
211  return res;
212 }
213 
215 {
216  return m_Devices.value(get_DefaultDeviceNumber());
217 }
218 
220 {
221  return m_Devices.value(dev);
222 }
223 
224 QScriptValue QPidController::device(int i) const
225 {
226  QPidDevicePtr dev = m_Devices.value(i);
227 
228  return m_ScriptEngine->newQObject(dev.data(), QScriptEngine::QtOwnership);
229 }
230 
232 {
233  stopController();
234 
235  set_DefaultDeviceNumber(dev);
236 
237  emit deviceListChanged();
238 }
239 
241 {
242  m_ScriptEngine->setDefaultDevice(getDevice(dev));
243 }
244 
245 void QPidController::setDeviceName(int dev, QString name)
246 {
247  QPidDevicePtr devp = m_Devices.value(dev);
248 
249  if (devp) {
250  devp -> set_DeviceName(name);
251  }
252 
253  emit deviceListChanged();
254 }
255 
257 {
258  QPidDevicePtr devp = m_Devices.value(dev);
259 
260  if (devp) {
261  devp -> configurationDialog();
262  }
263 }
264 
266 {
267  return get_DefaultDeviceNumber();
268 }
269 
271 {
272  if (get_SettingsPath() == "") {
273  QPidSettings settings;
274 
275  writeSettings(&settings);
276  } else {
277  saveSettings(get_SettingsPath());
278  }
279 }
280 
282 {
283  if (qcepDebug(DEBUG_PREFS)) {
284  printMessage("QPidController::writeSettings()");
285  }
286 
288 
289  if (win) {
290  set_WindowGeometry(win->saveGeometry());
291  set_WindowState(win->saveState(2));
292 
293  win->saveSplitterState(settings);
294  }
295 
296  QcepProperty::writeSettings(this, &staticMetaObject, "controller", settings);
297 
298  settings->beginWriteArray("selection");
299  int i=0;
300 
301  QMapIterator<QString,int> iter(m_ColumnSelections);
302 
303  while(iter.hasNext()) {
304  iter.next();
305 
306  settings->setArrayIndex(i++);
307  settings->setValue("name", iter.key());
308  settings->setValue("selection",iter.value());
309  }
310 
311  settings->endArray();
312 
313  settings->beginWriteArray("devices");
314 
315  for (int i=0; i<m_Devices.count(); i++) {
316  settings->setArrayIndex(i);
317  if (m_Devices.value(i)) {
318  QPidDevicePtr dev(m_Devices.value(i));
319 
320  settings->setValue("type", dev->get_DeviceType());
321  settings->setValue("name", dev->get_DeviceName());
322 
323  m_Devices.value(i)->writeSettings(settings, "device");
324  }
325  }
326 
327  settings->endArray();
328 
329  if (m_Server) {
330  m_Server->writeSettings(settings, "socketServer");
331  }
332 
333  if (m_Logger) {
334  m_Logger->writeSettings(settings, "logger");
335  }
336 }
337 
339 {
340  if (get_SettingsPath() == "") {
341  QPidSettings settings;
342 
343  readSettings(&settings);
344  } else {
345  loadSettings(get_SettingsPath());
346  }
347 }
348 
350 {
351  clearDevices();
352 
353  QcepProperty::readSettings(this, &staticMetaObject, "controller", settings);
354 
355  int nd = settings->beginReadArray("devices");
356 
357  for (int i=0; i<nd; i++) {
358  settings->setArrayIndex(i);
359 
360  int type = settings->value("type").toInt();
361  QString name = settings->value("name").toString();
362 
363  appendDevice(type, name);
364 
365  QPidDevicePtr dev = m_Devices.value(i);
366 
367  if (dev) {
368  dev->readSettings(settings, "device");
369  }
370  }
371 
372  settings->endArray();
373 
374  if (m_Server) {
375  m_Server->readSettings(settings, "socketServer");
376  }
377 
378  if (m_Logger) {
379  m_Logger->readSettings(settings, "logger");
380  }
381 
382  m_ColumnSelections.clear();
383 
384  int sz = settings->beginReadArray("selection");
385 
386  for (int i=0; i<sz; i++) {
387  settings->setArrayIndex(i);
388 
389  QString name = settings->value("name").toString();
390  int val = settings->value("selection").toInt();
391 
392  m_ColumnSelections[name] = val;
393  }
394 
395  settings->endArray();
396 
398 
399  if (win) {
400  QByteArray geometry = get_WindowGeometry();
401  QByteArray winstate = get_WindowState();
402 
403  if (!win->restoreGeometry(geometry)) {
404  printMessage("Restore geometry failed");
405  }
406 
407  if (!win->restoreState(winstate,2)) {
408  printMessage("Restore state failed");
409  }
410 
411  win->restoreSplitterState(settings);
412  }
413 
414  onDefaultDeviceChanged(get_DefaultDeviceNumber());
415 }
416 
417 void QPidController::loadSettings(QString filePath)
418 {
419  QPidSettings settings(filePath);
420 
421  readSettings(&settings);
422 
423  setSettingsFilePath(filePath);
424 }
425 
426 void QPidController::saveSettings(QString filePath)
427 {
428  QPidSettings settings(filePath);
429 
430  writeSettings(&settings);
431 
432  setSettingsFilePath(filePath);
433 }
434 
436 {
437  if (m_SettingsFilePath == "") {
438  return QDir::homePath();
439  } else {
440  return m_SettingsFilePath;
441  }
442 }
443 
445 {
446  m_SettingsFilePath = filePath;
447 }
448 
449 void QPidController::appendDevice(int deviceKind, QString deviceName)
450 {
451  QPidDeviceThreadPtr thread = QPidDeviceThread::createDevice(QPidControllerWPtr(this), deviceKind, deviceName);
452 
453  if (thread) {
454  thread->start();
455 
456  QPidDevicePtr dev = thread->waitForDevice();
457 
458  if (dev) {
459  m_DeviceThreads.append(thread);
460  m_Devices.append(dev);
461 
462  emit deviceListChanged();
463  }
464  }
465 }
466 
468 {
469  m_DeviceThreads.clear();
470  m_Devices.clear();
471 
472  emit deviceListChanged();
473 }
474 
475 void QPidController::deleteDevices(QVector<int> devList)
476 {
477  while (devList.count()) {
478  m_Devices.remove(devList.last());
479  m_DeviceThreads.remove(devList.last());
480  devList.pop_back();
481  }
482 
483  emit deviceListChanged();
484 }
485 
487 {
488  return m_Devices.count();
489 }
490 
492 {
493  return m_Server;
494 }
495 
497 {
498  return m_Logger;
499 }
500 
501 void QPidController::updateConnected(bool newConnected)
502 {
503  set_Connected(newConnected);
504 
505  if (!get_Connected()) {
506  set_Temperature(nan());
507  set_OutputLevel(nan());
508  set_RampPoint(nan());
509  }
510 }
511 
512 void QPidController::updateTemperature(double newTemperature)
513 {
514  set_Connected(true);
515  set_Temperature(newTemperature);
516 }
517 
518 void QPidController::updateRampPoint(double newRampPoint)
519 {
520  set_Connected(true);
521  set_RampPoint(newRampPoint);
522 }
523 
524 void QPidController::updateOutputLevel(double newOutputLevel)
525 {
526  set_Connected(true);
527  set_OutputLevel(newOutputLevel);
528 }
529 
531 {
532  QScriptValue result = m_ScriptEngine->evaluate(cmd);
533 
534  printMessage(result.toString());
535 }
536 
538 {
539  QScriptValue result = m_ScriptEngine->evaluate(cmd);
540 
541  QPidServerSessionPtr sess(wksess);
542 
543  if (sess) {
544  QMetaObject::invokeMethod(sess.data(), "finishedCommand", Q_ARG(QScriptValue, result));
545  }
546 }
547 
549 {
550  printMessage("Available Serial Ports:");
551 
552  QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();
553 
554  for (int i=0; i<ports.count(); i++) {
555  QextPortInfo port = ports.value(i);
556 
557  printMessage(tr("Port %1").arg(i));
558  printMessage(tr("Port Name: %1").arg(port.portName));
559  printMessage(tr("Phys Name: %1").arg(port.physName));
560  printMessage(tr("Frnd Name: %1").arg(port.friendName));
561  printMessage(tr("Enum Name: %1").arg(port.enumName));
562  printMessage("");
563  }
564 }
565 
567 {
568  if (get_SoakTime() > 0) {
569  double soakTime = get_SoakTime();
570 
571  if (get_HeatRampRate() > 0) {
572  soakTime += fabs((get_HeatSetPoint() - get_SetPoint())/get_HeatRampRate());
573  }
574 
575  connect(&m_RampSoakTimer, SIGNAL(timeout()), this, SLOT(onRampSoakTimer()));
576 
577  printMessage(tr("Ramping from %1 to %2 at %3 / min")
578  .arg(get_SetPoint()).arg(get_HeatSetPoint()).arg(get_HeatRampRate()));
579 
580  m_RampSoakTimer.start(soakTime*60.0*1000.0);
581  }
582 }
583 
585 {
586  disconnect(&m_RampSoakTimer, SIGNAL(timeout()), this, SLOT(onRampSoakTimer()));
587 }
588 
590 {
591  printMessage(tr("Cooling from %1 to %2 at %3 / min")
592  .arg(get_HeatSetPoint()).arg(get_SetPoint()).arg(get_CoolRampRate()));
593 
594  disconnect(&m_RampSoakTimer, SIGNAL(timeout()), this, SLOT(onRampSoakTimer()));
595 }
596 
598 {
600 
601  if (dev) {
602  dev->sendCommand(cmd);
603  }
604 }
605 
607 {
609 
610  if (dev) {
611  dev->autoTune();
612  }
613 }
614 
616 {
618 
619  if (logger) {
620  logger->logChannelNames(names);
621  }
622 }
623 
624 void QPidController::onLoggedChannelValues(QcepDoubleList values)
625 {
627 
628  if (logger) {
629  logger->logChannelValues(values);
630  }
631 }
632 
634 {
635  set_ColumnNames(names);
636 
637  int n=names.length();
638 
639  for (int i=m_PlottedValues.length(); i<n; i++) {
640  m_PlottedValues.append(QVector<double>());
641  }
642 
644 
645  if (window) {
646  window->graphChannelNames(names);
647  }
648 }
649 
650 void QPidController::onGraphedChannelValues(QcepDoubleList values)
651 {
652  int n = values.length();
653  int np = get_GraphLength();
654 
655  for (int i=m_PlottedValues.length(); i<n; i++) {
656  m_PlottedValues.append(QVector<double>());
657  }
658 
659  for (int i=0; i<n; i++) {
660  m_PlottedValues[i].append(values[i]);
661 
662  int l = m_PlottedValues[i].count();
663 
664  if (l > np) {
665  m_PlottedValues[i].remove(0, l-np);
666  }
667  }
668 
670 
671  if (window) {
672  window->graphChannelValues(values);
673  }
674 }
675 
676 Qt::CheckState QPidController::yChecked(int col)
677 {
678  QString name = get_ColumnNames().value(col);
679 
680  int sel = m_ColumnSelections.value(name);
681 
682  return (sel & 1 ? Qt::Checked : Qt::Unchecked);
683 }
684 
685 Qt::CheckState QPidController::y2Checked(int col)
686 {
687  QString name = get_ColumnNames().value(col);
688 
689  int sel = m_ColumnSelections.value(name);
690 
691  return (sel & 2 ? Qt::Checked : Qt::Unchecked);
692 }
693 
694 void QPidController::setYChecked(int col, Qt::CheckState state)
695 {
696  QString name = get_ColumnNames().value(col);
697 
698  if (name.length()) {
699  int val = m_ColumnSelections.value(name);
700 
701  if (state == Qt::Checked) {
702  val |= 1;
703  } else if (state == Qt::Unchecked) {
704  val &= ~1;
705  }
706 
707  m_ColumnSelections[name] = val;
708 
709  prop_SelectionCounter()->incValue(1);
710  }
711 }
712 
713 void QPidController::setY2Checked(int col, Qt::CheckState state)
714 {
715  QString name = get_ColumnNames().value(col);
716 
717  if (name.length()) {
718  int val = m_ColumnSelections.value(name);
719 
720  if (state == Qt::Checked) {
721  val |= 2;
722  } else if (state == Qt::Unchecked) {
723  val &= ~2;
724  }
725 
726  m_ColumnSelections[name] = val;
727 
728  prop_SelectionCounter()->incValue(1);
729  }
730 }
void restoreSplitterState(QPidSettings *settings)
void onGraphedChannelNames(QStringList names)
void setYChecked(int col, Qt::CheckState state)
void setSettingsFilePath(QString filePath)
void executeServerCommand(QPidServerSessionWPtr wksess, QString cmd)
QVector< QPidDeviceThreadPtr > m_DeviceThreads
QPidLoggerThreadPtr m_LoggerThread
QSharedPointer< QPidDevice > QPidDevicePtr
Definition: qpiddevice-ptr.h:6
QTimer m_RampSoakTimer
QWeakPointer< QPidController > QPidControllerWPtr
QWeakPointer< QPidServerSession > QPidServerSessionWPtr
void onGraphedChannelValues(QcepDoubleList values)
QPidObjectNamer m_ObjectNamer
void saveSplitterState(QPidSettings *settings)
QSharedPointer< QPidLogger > QPidLoggerPtr
Definition: qpidlogger-ptr.h:6
QPidMainWindowWPtr m_MainWindow
QcepSettingsSaverPtr saver()
QString settingsFilePath() const
static double nan()
QPidDevicePtr defaultDevice() const
QVector< QPidDevicePtr > m_Devices
void setDefaultDevice(int dev)
QSharedPointer< QPidScriptEngine > QPidScriptEnginePtr
Qt::CheckState yChecked(int col)
void graphChannelNames(QStringList names)
void onLoggedChannelValues(QcepDoubleList values)
QSharedPointer< QPidDeviceThread > QPidDeviceThreadPtr
void executeCommand(QString cmd)
QSharedPointer< QPidServerSession > QPidServerSessionPtr
void configurationDialog(int dev)
QString controllerStatusString(int status)
void setDeviceName(int dev, QString name)
QPidServerPtr m_Server
void updateOutputLevel(double newOutputLevel)
QPidLoggerPtr logger()
void graphChannelValues(QcepDoubleList values)
void deleteDevices(QVector< int > devList)
void deviceListChanged()
QPidDevicePtr getDevice(int dev) const
QString m_SettingsFilePath
QScriptValue device(int i) const
void updateTemperature(double newTemperature)
void start(QPidMainWindowWPtr window, QPidControllerWPtr ctrl)
void onLoggedChannelNames(QStringList names)
void sendCommand(QString cmd)
QcepSettingsSaverPtr m_Saver
virtual ~QPidController()
void appendDevice(int deviceKind, QString deviceName)
QPidScriptEnginePtr m_ScriptEngine
void debugChanged(int dbg)
QSharedPointer< QPidLoggerThread > QPidLoggerThreadPtr
void criticalMessage(QString msg)
void updateRampPoint(double newRampPoint)
void saveSettings(QString filePath)
QMap< QString, int > m_ColumnSelections
QPidLoggerPtr m_Logger
void onDefaultDeviceChanged(int dev)
void printMessage(QString msg, QDateTime dt=QDateTime::currentDateTime())
void setY2Checked(int col, Qt::CheckState state)
QList< QVector< double > > m_PlottedValues
void loadSettings(QString filePath)
QPidServerPtr server()
void updateConnected(bool newConnected)
QPidController(QObject *parent=0)
int defaultDeviceNumber() const
QPidServerThreadPtr m_ServerThread
QSharedPointer< QPidServer > QPidServerPtr
Definition: qpidserver-ptr.h:6
static QPidDeviceThreadPtr createDevice(QPidControllerWPtr ctl, int deviceKind, QString deviceName)
Qt::CheckState y2Checked(int col)
QSharedPointer< QPidServerThread > QPidServerThreadPtr