dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
smartsavebutton.cpp
Go to the documentation of this file.
1 
16 /*
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 3 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful, but
23  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
24  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25  * for more details.
26  *
27  * You should have received a copy of the GNU General Public License along
28  * with this program; if not, see <http://www.gnu.org/licenses/>
29  *
30  * Additional note on redistribution: The copyright and license notices above
31  * must be maintained in each individual source file that is a derivative work
32  * of this source file; otherwise redistribution is prohibited.
33  */
34 #include "smartsavebutton.h"
35 
37 {
38 }
39 
47 void smartSaveButton::addButtons(QPushButton *save, QPushButton *apply)
48 {
49  buttonList.insert(save, save_button);
50  buttonList.insert(apply, apply_button);
51  connect(save, SIGNAL(clicked()), this, SLOT(processClick()));
52  connect(apply, SIGNAL(clicked()), this, SLOT(processClick()));
53 }
54 
61 void smartSaveButton::addApplyButton(QPushButton *apply)
62 {
63  buttonList.insert(apply, apply_button);
64  connect(apply, SIGNAL(clicked()), this, SLOT(processClick()));
65 }
66 
74 {
75  buttonList.insert(save, save_button);
76  connect(save, SIGNAL(clicked()), this, SLOT(processClick()));
77 }
78 
82 void smartSaveButton::processClick()
83 {
84  emit beginOp();
85  bool save = false;
86  QPushButton *button = qobject_cast<QPushButton *>(sender());
87  if (!button)
88  return;
89  if (buttonList.value(button) == save_button)
90  save = true;
91  processOperation(button, save);
92 }
93 
101 void smartSaveButton::processOperation(QPushButton *button, bool save)
102 {
103  emit preProcessOperations();
104  QStringList failedUploads;
105  QStringList failedSaves;
106  QStringList missingObjects;
107  if (button) {
108  button->setEnabled(false);
109  button->setIcon(QIcon(":/uploader/images/system-run.svg"));
110  }
111  QTimer timer;
112  timer.setSingleShot(true);
113  ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance();
114  UAVObjectUtilManager *utilMngr = pm->getObject<UAVObjectUtilManager>();
115  foreach (UAVDataObject *obj, objects) {
116  if (!obj->getIsPresentOnHardware() && obj->isSettings()) {
117  if (mandatoryList.value(obj, true))
118  missingObjects.append(obj->getName());
119  continue;
120  }
121  UAVObject::Metadata mdata = obj->getMetadata();
123  if (mandatoryList.value(obj, true))
124  failedUploads.append(obj->getName());
125  continue;
126  }
127  upload_result = false;
128  current_object = obj;
129 
130  // We only allow to send/save Settings objects using this method
131  if (!obj->isSettings()) {
132  qDebug() << "[smartsavebutton.cpp] Error, tried to apply/save a non-settings object: "
133  << obj->getName();
134  continue;
135  }
136 
137  qDebug() << "[smartsavebutton.cpp] Sending object to remote end - " << obj->getName();
138  connect(obj, SIGNAL(transactionCompleted(UAVObject *, bool)), this,
139  SLOT(transaction_finished(UAVObject *, bool)));
140  connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
141  obj->updated();
142  // Three things can happen now:
143  // - If object is ACK'ed then we'll get a transactionCompleted signal once ACK arrives
144  // with a success value at 'true'
145  // - If remote side does not know it, or object is not ACK'ed then we'll get a timeout,
146  // which we catch below
147  // - If object is ACK'ed and message gets lost, we'll get a transactionCompleted with a
148  // success value at 'false'
149  //
150  // Note: settings objects should always be ACK'ed, so a timeout should always be because of
151  // a lost
152  // message over the telemetry link.
153  //
154  // Note 2: the telemetry link does max 3 tries with 250ms interval when sending an object
155  // update over the link
156  timer.start(1000);
157  loop.exec();
158  if (!timer.isActive())
159  qInfo() << "[smartsavebutton.cpp] Upload timeout for object" << obj->getName();
160  timer.stop();
161  disconnect(obj, SIGNAL(transactionCompleted(UAVObject *, bool)), this,
162  SLOT(transaction_finished(UAVObject *, bool)));
163  disconnect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
164 
165  if (upload_result == false) {
166  qInfo() << "[smartsavebutton.cpp] Object upload error:" << obj->getName();
167  if (mandatoryList.value(obj, true))
168  failedUploads.append(obj->getName());
169  continue;
170  }
171 
172  // Now object is uploaded, we can move on to saving it to flash:
173  save_result = false;
174  current_objectID = obj->getObjID();
175 
176  if (save && (obj->isSettings())) {
177  qDebug() << "[smartsavebutton.cpp] Save request for object" << obj->getName();
178  connect(utilMngr, SIGNAL(saveCompleted(int, bool)), this,
179  SLOT(saving_finished(int, bool)));
180  connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
181  utilMngr->saveObjectToFlash(obj);
182  // Now, here is what will happen:
183  // - saveObjectToFlash is going to attempt the save operation
184  // - If save succeeds, then it will issue a saveCompleted signal with the ObjectID and
185  // 'true'
186  // - If save fails, either because of error or timeout, then it will issue a
187  // saveCompleted signal
188  // with the ObjectID and 'false'.
189  //
190  // Note: in case of link timeout, the telemetry layer will retry up to 2 times, we don't
191  // need to retry ourselves here.
192  //
193  // Note 2: saveObjectToFlash manages save operations in a queue, so there is no
194  // guarantee that
195  // the first "saveCompleted" signal is for the object we just asked to save.
196  timer.start(2000);
197  loop.exec();
198  if (!timer.isActive())
199  qInfo() << "[smartsavebutton.cpp] Saving timeout for object" << obj->getName();
200  timer.stop();
201  disconnect(utilMngr, SIGNAL(saveCompleted(int, bool)), this,
202  SLOT(saving_finished(int, bool)));
203  disconnect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
204 
205  if (save_result == false) {
206  qInfo() << "[smartsavebutton.cpp] failed to save:" << obj->getName();
207  if (mandatoryList.value(obj, true))
208  failedSaves.append(obj->getName());
209  }
210  }
211  }
212  if (button)
213  button->setEnabled(true);
214  QString result;
215  bool error = true;
216  if (failedSaves.isEmpty() && failedUploads.isEmpty() && missingObjects.isEmpty()) {
217  result = "All operations finished successfully";
218  error = false;
219  } else {
220  if (!failedSaves.isEmpty()) {
221  result.append("Objects not saved:\n");
222  foreach (QString str, failedSaves) {
223  result.append(str + "\n");
224  }
225  }
226  if (!failedUploads.isEmpty()) {
227  if (!result.isEmpty())
228  result.append("\n");
229  result.append("Objects not uploaded:\n");
230  foreach (QString str, failedUploads) {
231  result.append(str + "\n");
232  }
233  }
234  if (!missingObjects.isEmpty()) {
235  if (!result.isEmpty())
236  result.append("\n");
237  result.append("Objects not present on the hardware:\n");
238  foreach (QString str, missingObjects) {
239  result.append(str + "\n");
240  }
241  }
242  }
243  qDebug() << "RESULT" << result << missingObjects << failedSaves << failedUploads;
244  if (button)
245  button->setToolTip(result);
246  if (!error) {
247  if (button)
248  button->setIcon(QIcon(":/uploader/images/dialog-apply.svg"));
249  emit saveSuccessfull();
250  } else {
251  if (button) {
252  if (!failedSaves.isEmpty() || !failedUploads.isEmpty())
253  button->setIcon(QIcon(":/uploader/images/process-stop.svg"));
254  else
255  button->setIcon(QIcon(":/uploader/images/warning.svg"));
256  }
257  }
258  emit endOp();
259 }
260 
267 {
268  objects = list;
269 }
270 
278 {
279  Q_ASSERT(obj);
280  if (!objects.contains(obj))
281  objects.append(obj);
282 }
283 
292 void smartSaveButton::addObject(UAVDataObject *obj, bool isMandatory)
293 {
294  Q_ASSERT(obj);
295  if (!objects.contains(obj))
296  objects.append(obj);
297  if (!isMandatory)
298  mandatoryList.insert(obj, false);
299 }
300 
308 {
309  if (objects.contains(obj))
310  objects.removeAll(obj);
311 }
312 
318 {
319  objects.clear();
320 }
321 
323 {
324  objects.clear();
325 }
326 
327 void smartSaveButton::transaction_finished(UAVObject *obj, bool result)
328 {
329  if (current_object == obj) {
330  upload_result = result;
331  loop.quit();
332  }
333 }
334 
335 void smartSaveButton::saving_finished(int id, bool result)
336 {
337  // The saveOjectToFlash method manages its own save queue, so we can be
338  // in a situation where we get a saving_finished message for an object
339  // which is not the one we're interested in, hence the check below:
340  if ((quint32)id == current_objectID) {
341  save_result = result;
342  loop.quit();
343  }
344 }
345 
347 {
348  foreach (QPushButton *button, buttonList.keys())
349  button->setEnabled(value);
350 }
351 
353 {
354  foreach (QPushButton *button, buttonList.keys()) {
355  button->setToolTip("");
356  button->setIcon(QIcon());
357  }
358 }
359 
365 {
366  mandatoryList.insert(obj, false);
367 }
368 
370 {
371  processOperation(NULL, false);
372 }
373 
375 {
376  processOperation(NULL, true);
377 }
void addApplyButton(QPushButton *apply)
smartSaveButton::addApplyButton Called only by the ConfigTaskWidget when adding the smart save button...
void removeAllObjects()
smartSaveButton::removeAllObjects Remove all tracked objects at once.
void addSaveButton(QPushButton *save)
smartSaveButton::addSaveButton Called only by the ConfigTaskWidget when adding the smart save buttons...
void addButtons(QPushButton *save, QPushButton *apply)
smartSaveButton::addButtons Called only by the ConfigTaskWidget when adding the smart save buttons...
void removeObject(UAVDataObject *obj)
smartSaveButton::removeObject The smartSaveButton contains a list of objects it will work with...
void enableControls(bool value)
Core plugin system that manages the plugins, their life cycle and their registered objects...
Definition: pluginmanager.h:53
void addObject(UAVDataObject *)
smartSaveButton::addObject The smartSaveButton contains a list of objects it will work with...
void saveObjectToFlash(UAVObject *obj)
UAVObjectUtilManager::saveObjectToSD Add a new object to save in the queue.
void updated()
Definition: uavobject.cpp:179
bool getIsPresentOnHardware() const
void preProcessOperations()
quint32 getObjID()
Definition: uavobject.cpp:107
void setNotMandatory(UAVDataObject *)
QString getName()
Definition: uavobject.cpp:131
Metadata getMetadata()
void setObjects(QList< UAVDataObject * >)
smartSaveButton::setObjects Sets all monitored objects in one operation
else error('Your technical computing program does not support file choosers.Please input the file name in the argument. ') end elseif nargin >0 logfile
void saveSuccessfull()
save(matfile $(SAVEOBJECTSCODE))
static AccessMode GetGcsAccess(const Metadata &meta)
Definition: uavobject.cpp:397